Gå til innhold

Den store project euler tråden


Anbefalte innlegg

Liten forbedring nå, men må jo likevel prøve ett og ett nummer, blir jo ren "gjettelek".

 

 

 

	n = input('');

kvtall = sum(1:n)
a = 0;

for i = 1:kvtall
	if mod(kvtall, i) == 0
		a = a + 1;
	end
end

a

Tar likevel en liten evighet å regne ut tall over 1000. Altså en så og si ubrukelig kode :wallbash:

 

 

 

Edit: Surrer nå, dette var jo problem nr. 12.

 

Edit2: Finnes det noen innbygd funksjon i MATLAB som kan faktorisere 28 til 1,2,4,7,14,28.

 

 

Den jeg vet om faktoriserer slik:

>> factor(28)
ans =

  2   2   7

>>

 

 

Endret av runesole
Lenke til kommentar
Videoannonse
Annonse
Edit: Surrer nå, dette var jo problem nr. 12.

 

#12 var veldig morsom, og jeg bruke masse tid på den, og det første utkastet var dessverre langt i fra raskt.

 

 

 

Tips #1 vi trenger å regne ut alle divisorer til et tall. Hva kan man si om divisorer til N som er større enn sqrt(N)? Kan dette utnyttes for å forbedre kjøretiden til divisorberegningen? Ekstrahint: for divisorer av 28, trenger du ikke å *regne ut* 7, 14 eller 28.

 

Tips #2 Slike triangle tall kan regnes ut vha en formel -- gitt her.

 

Tips #3 Hva kan man si om divisorer til x og x+1 for to vilkårlige positive heltall x? (eller, rettere sagt, hvor mange divisorer har x og x+1 til felles?)

 

Disse tips tilsammen gir:

$ python ~/src/projecteuler.net/problem-012/problem12.py

puzzle 12, solution: <sensur> (in 0.274605s)

 

 

Endret av zotbar1234
Lenke til kommentar
Tips #1:Må vel vite alle faktorene når det er det oppgaven går ut på å finne?

 

Nei, egentlig ikke -- man må *telle* hvor mange det er, ikke *hvilke* det er. Dvs det holder å vite at 28 har 6 divisorer. Vi trenger *ikke* å vite *hva* disse 6 divisorer er.

 

Tips #2: Funker slik med MATLAB:

>> sum(1:7)
ans =  28
>>

 

Tips 2 og 3 må sees på under ett :) At matlab har en ferdig funksjon for det er litt uvesentlig. Tipset er språkuavhengig.

Lenke til kommentar
Kode:

 

 

clear
j = 20;
D = 1;

while D != 0

	for i = 1:20
			A(i) = mod(j, i);
	end

	D = sum(A);
	j = j + 20;

end

disp(j-20)

 

 

 

Ganske sikker på den stemmer, da jeg får rett svar for tall opptil 10.

!= er vel ~= i matlab?

Merker jeg rusten i matte :hmm:

Da kjøre koden din greit oss meg,ca 50sek.

Et tips til euler 5 er least_common_multiples

 

Euler 5 matlab,da går det unna.

num = 11;
for i = 12:20
  num = lcm(num, i);
end

Lenke til kommentar
@Jann_Ove: Takk, det korter tiden ned til ca 1,5 timer. :thumbup: Vet ikke hvordan jeg skal gå frem for å lære meg python.

 

 

Føkk Matlab :realmad:

 

Den klarte jeg faktisk å bruteforce på 30 sekund i matlab. Men det var kanskje ikke problem 15 - du hadde skrevet feil? Si ifra om det var nr 15 og om du vil ha tips :)

Lenke til kommentar

 

 

>> type euler14
euler14 is the user-defined function defined from: C:\***\euler14.m

makslengde = 0;
nmax = 0;

for n = 1:1000000

	teller = n;
	A = [];
	A(1) = n;
	k = 2;

	while n > 1

			if round(n/2) != n/2
					n = 3*n + 1;
			else
					n = n/2;
			end

			A(k) = n;
			k = k + 1;

	end

	lengde = length(A);

	if makslengde < lengde
			makslengde = lengde;
			nmax = teller;
	end

	n = teller;

end

makslengde
nmax
>>

 

 

Lenke til kommentar
Lykke:

>> clear
>> for i = 1
> tic
> euler14
> toc
> end
makslengde =  525
nmax =  837799
Elapsed time is 7558.525 seconds.
>>

 

Elapsed time is 7558.525 seconds. :fun:

W00t? Hvordan fikk du så horribel ytelse?

 

524

837799

finished in 3450 ms

 

Jeg mer eller mindre blåkopierte koden din i C#.

Lenke til kommentar
Etter å ha rappet en funksjon som lager finner alle divisorer ble prob 12 veldig lett :thumbup:

 

Hvor rappet du den? :)

 

 

flagg = true;
n = 1;

while flagg

kvtall = sum(1:n);
	l = length(divisor(kvtall));
	if l > 500
		flagg = false;
	end
n = n + 1;
end

kvtall

 

 

 

 

- Den viktigste observasjonen er at en funksjon som regner antall divisorer av N ikke trenger å sjekke større tall enn sqrt(N) -- når 4 er en divisor av 28, så vil også 28/4 = 7 være det. Dette betyr at for hver divisor i intervallet [1,ceil(sqrt(N))) du finner, legger du 2 til antall divisorer funnet hittil. Det kreves en liten justering for tall som er kvadrater, opplagt, men dette er ideen.

 

- Den andre viktige observasjon er at alle trekanttall er på formen (x*(x+1))/2 (hvorfor det?) OG, siden gcd(x,x+1) = 1, så har ikke x eller x+1 noen divisorer til felles. Dvs. gitt et trekanttall N = (x*(x+1))/2, så er antall divisorer av N lik divisors(x) * divisors(x+1).

 

Disse to tilsammen gjør at man bruker godt under 1 sekund med tid. Det er nettopp den type observasjoner som gjør det mulig å løse enhver oppgave selv i språk uten raske (ift. standard C/Fortran) implementasjoner på i verste fall noen få sekunder. Bruce force er så å si *aldri* løsningen. Mao, det er *ikke* matlab som er problemet -- matlab er mer enn rask nok til samtlige av oppgavene.

 

 

Endret av zotbar1234
Lenke til kommentar
Har de fleste språk en innebygd fn. for å vise alle divisorene?

 

Dette er totalt uvesentlig -- man skriver en selv, soklart. Mathematica har f.eks. veldig mye stæsj tilgjengelig (som er garantert veldig veldig optimalisert), men det er aldri interessant. Etter hver skriver man en liten euler-modul med antall divisorer, liste av primtall og alle de andre oppgavene som dukker opp "ofte".

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...