Skip to content

fw42/projecteuler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 

Repository files navigation

Project Euler solutions in Ruby

fw

Bei Project Euler handelt es sich um eine Webseite mit einer Art "Programmierwettbewerb" für mehr oder weniger komplexe mathematische Problemstellungen, in erster Linie zahlentheoretischer Natur. Das Problem (bzw. der Reiz) der meisten Aufgaben ist, dass sie prinzipiell sehr leicht zu lösen sind, die Lösung, auf die man "direkt" kommt aber meistens extrem ineffizient ist und man sich etwas mit dem mathematischen Background beschäftigen muss, um den eigenen Algorithmus zu optimieren. Da ich schon lange die Programmiersprache Ruby lernen wollte war das eine gute Gelegenheit für mich.

Die meisten meiner Lösungen sind nicht besonders effizient (und teilweise vermutlich auch mathematisch nicht wirklich optimal). Mein Ziel war es Ruby zu lernen, nicht die Aufgaben möglichst geschickt zu lösen. Dennoch sind fast alle meine Lösungen in deutlich weniger als einer Minute (die meisten sogar in weniger als einer Sekunde auf einem halbwegs aktuellen Prozessor) ausführbar (und das obwohl Ruby eine relativ langsam interpretierte Sprache ist).

Viele der Aufgaben sind etwas eleganter lösbar, wenn man Ruby Libraries benutzt (z.B. die Prime Klasse aus 'mathn'). Ich habe darauf absichtlich verzichtet, da ich alle Algorithmen selbst implementieren wollte.

Achtung: Viele Leute beschweren sich darüber, dass im Netz Lösungen zu den Aufgaben veröffentlicht werden. Ich habe kein Problem damit, im Gegenteil, ich finde es sinnvoll, dass Lösungen veröffentlicht werden damit man sich auch andere Ansätze anschauen und dadurch noch mehr über das Problem lernen kann. Bis auf ein paar wenige Ausnahmen habe ich alle Probleme vollständig selbst gelöst und mir erst im Nachhinein die Programme anderer angeschaut. Wer die Lösungen einfach nur kopiert um möglichst viele Probleme abzuhaken ist selbst schuld! Dadurch verdirbt man sich nur den Spass ohne jeglichen Nutzen davon zu haben.

Problem 1

Find the sum of all the multiples of 3 or 5 below 1000.

001.rb

Stichwort kleiner Gauss.

Problem 2

Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed four million.

002.rb

Problem 3

What is the largest prime factor of the number 600851475143 ?

003.rb

Diese Lösung gefällt mir sehr gut. Sie ist extrem schnell (O(n1/2 log2(n))), gleichzeitig sehr einfach zu verstehen und benutzt nur indirekt irgendwelche Eigenschaften von Primzahlen. Ein Beweis der Korrektheit findet sich in Primality testing in deterministic polynomial time von Professor Michiel Smid (Seite 24 und 25).

Problem 4

Find the largest palindrome made from the product of two 3-digit numbers.

004.rb

Optimierung: Palindrome gerader Länge sind immer durch 11 teilbar.

Problem 5

What is the smallest number that is evenly divisible by all of the numbers from 1 to 20?

005.rb

Stichwort kleinstes gemeinsames Vielfaches.

Problem 6

Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.

006.rb

Stichwort Gaussche Summenformeln.

Problem 7

What is the 10001st prime number?

007.rb

Stichwort Primzahlsatz und Primzahlsieb.

Problem 8

Find the greatest product of five consecutive digits in the 1000-digit number.

008.rb

Problem 9

There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the product abc.

009.rb

Problem 10

Find the sum of all the primes below two million.

010.rb

Problem 11

What is the greatest product of four adjacent numbers in any direction (up, down, left, right, or diagonally) in the 20x20 grid?

011.rb

Nicht so schön. Mehr oder weniger Brute Force, läuft aber in wenigen Millisekunden.

Problem 12

What is the value of the first triangle number to have over five hundred divisors?

012.rb

Problem 13

Work out the first ten digits of the sum of the following one-hundred 50-digit numbers.

013.rb

Problem 14

The following iterative sequence is defined for the set of positive integers:
n -> n/2 (n is even)
n -> 3n + 1 (n is odd)
Which starting number, under one million, produces the longest chain?

014.rb

Stichwort Dynamic Programming.

Problem 15

How many routes are there through a 20x20 grid?

015.rb

Stichwort Dynamic Programming.

Problem 16

What is the sum of the digits of the number 21000?

016.rb

Naja, das geht bestimmt auch "mathematischer" :-)

Problem 17

If all the numbers from 1 to 1000 ("one thousand") inclusive were written out in words, how many letters would be used?

017.rb

Problem 18

Find the maximum total from top to bottom of the triangle below.

018.rb

Problem 19

How many Sundays fell on the first of the month during the twentieth century?

019.rb

Idee: Zellers Kongruenz. Hätte man einfacher haben können mit den Ruby Date Funktionen, wollte ich aber nicht.

Problem 20

Find the sum of digits in 100!

020.rb

Siehe Problem 16.

Problem 21

Let d(n) be defined as the sum of proper divisors of n. If d(a) = b and d(b) = a, where a != b, then a and b are an amicable pair and each of a and b are called amicable numbers. Evaluate the sum of all the amicable numbers under 10000.

021.rb

Problem 22

Using names.txt, a text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score. For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714. What is the total of all the name scores in the file?

022.rb

Schön kurz! Fast so unlesbar wie Perl Code :-)

Problem 23

It can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.

023.rb

Doofe Lösung für eine doofe Aufgabe.

Problem 24

What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?

024.rb

Hier muss ich zugeben, dass ich nur auf extrem langsame Lösungen gekommen bin und daher etwas gegooglet habe. Die Idee ist von Chris Smith geklaut.

Problem 25

What is the first term in the Fibonacci sequence to contain 1000 digits?

025.rb

Problem 26

Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.

026.rb

Mögliche Optimierung: Zahlen mit endlicher Entwicklung von vornerein ausschliessen (das sind genau die, die keine anderen Primteiler als 2 oder 5 haben).

Problem 27

Euler published the remarkable quadratic formula: n2 + n + 41. It turns out that the formula will produce 40 primes for the consecutive values n = 0 to 39. Considering quadratics of the form: n2 + an + b, where |a| < 1000 and |b| < 1000. Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0.

027.rb

Sehr interessante Aufgabe (siehe auch hier)! Ideen: an n=0 sieht man, dass b prim sein muss (und positiv) und an n=1 sieht man, dass a+b+1 ebenfalls prim sein muss.

Problem 28

Starting with the number 1 and moving to the right in a clockwise direction a n by n spiral is formed. What is the sum of both diagonals in a 1001 by 1001 spiral?

028.rb

Nette Aufgabe, nicht soo schöne Lösung, aber schnell (< 1 ms).

Problem 29

How many distinct terms are in the sequence generated by ab for 2 <= a,b <= 100?

029.rb

Ziemlich straight-forward und schön kurz :-)

Problem 30

Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.

030.rb

Gleicher Algorithmus wie bei 34.

Problem 31

How many different ways can £2 be made using any number of coins?

031.rb

Problem 32

The product 7254 is unusual, as the identity, 39 x 186 = 7254, containing multiplicand, multiplier, and product is 1 through 9 pandigital. Find the sum of all products whose multiplicand/multiplier/product identity can be written as a 1 through 9 pandigital.

032.rb

Idee: Durch Abschätzungen des Logarithmus zur Basis 10 und der Gaussklammer, kann man leicht zeigen, dass 4 - length(a) <= length(b) <= 5 - length(a) gelten muss. Das schränkt den Suchraum bereits deutlich ein. Weiterhin müssen keine Zahlen getestet werden, die die Ziffer 0 enthalten oder die eine Ziffer doppelt enthalten.

Problem 33

The fraction 49/98 is a curious fraction (...) 49/98 = 4/8, which is correct (...). There are exactly four non-trivial examples of this type of fraction, less than one in value, and containing two digits in the numerator and denominator. If the product of these four fractions is given in its lowest common terms, find the value of the denominator.

033.rb

Winzige Optimierung: (10a+b)/(10b+c) = a/c gilt genau dann, wenn (9a+b)c = 10ab.

Problem 34

Find the sum of all numbers which are equal to the sum of the factorial of their digits.

034.rb

Idee: 7*9! ist eine obere Schranke, denn ab 7 Ziffern ist die größtmögliche Zahl (alle Ziffern 9) größer als die größtmögliche Summe der Fakultäten der Ziffern (Anzahl Ziffern mal 9!). Als kleine Optimierung werden noch Summen in einer Tabelle gespeichert (hat bei mir fast einen Faktor von 3 ausgemacht).

Problem 35

The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime. How many circular primes are there below one million?

035.rb

Diese Lösung gefällt mir nicht wirklich, sie ist viel zu langsam. Eine mögliche Optimierung: Die Dezimalentwicklung einer zirkulären Primzahl kann niemals die Ziffern 0,2,4,5,6 oder 8 enthalten.

Problem 36

Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2.

036.rb

Ruby ist toll :-)

Problem 37

The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3. Find the sum of the only eleven primes that are both truncatable from left to right and right to left. (NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes)

037.rb

Sehr schöne Aufgabe mit einer sehr schnellen Lösung. Naiver Ansatz: Liste von Primzahlen erstellen (mit einem Primzahlsieb), dann dadrin die truncatables rausfischen. Leider viel zu langsam. Besserer Ansatz: Alle truncatable Primes on-the-fly generieren (mit Trial Division als Test statt dem Sieb) und dabei ausnutzen, dass diese nicht die Ziffern 0, 4, 6 und 8 enthalten können (sonst ist eine der Zahlen gerade), nicht mit 1 anfangen und nicht mit 1 enden können (1 ist nicht prim) und nicht zwei aufeinander folgende gleiche Ziffern enthalten können (sonst ist eine der Zahlen durch 11 teilbar).

Problem 39

If p is the perimeter of a right angle triangle {a,b,c}, which value, for p <= 1000, has the most solutions?

039.rb

Schöne Aufgabe. Erste Idee: Für alle p<=1000 alle möglichen pythagoräischen Tripel generieren. Das war allerdings viel zu langsam. Neue Idee: Alle möglichen Tripel generieren, deren Summe kleiner als 1000 ist, und dann hinterher das Maximum suchen.

Problem 38

What is the largest 1 to 9 pandigital 9-digit number that can be formed as the concatenated product of an integer with (1,2, ... , n) where n > 1?

038.rb

Problem 40

An irrational decimal fraction is created by concatenating the positive integers. If dn represents the nth digit of the fractional part, find the value of the following expression: d1 × d10 × d100 × d1000 × d10000 × d100000 × d1000000

040.rb

Eigentlich hätte ich gerne eine Formel gehabt um die Ziffern direkt zu berechnen (ohne ALLE anderen auch zu speichern). Habe dann aber aufgegeben, als ich gemerkt habe, dass es auf diese (dumme) Weise immernoch recht schnell (~1 Sekunde) ist.

Problem 41

What is the largest n-digit pandigital prime that exists?

041.rb

Idee: Die Zahl kann weder 8-pandigital noch 9-pandigital sein, denn solche Zahlen haben eine Quersumme von 3 und sind damit selbst durch 3 teilbar, also nicht prim. (Anmerkung zum Code: 5039 = 7!-1. perm(k,s) erzeugt für jedes 0 <= k < s.length! eine eindeutige Permutation von s)

Problem 42

Using words.txt, a 16K text file containing nearly two-thousand common English words, how many are triangle words (sum of alphabetical values of letters is a triangle number)?

042.rb

Problem 43

The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a rather interesting sub-string divisibility property.

Let d1 be the 1st digit, d2 be the 2nd digit, and so on. In this way, we note the following:

  • d2 d3 d4 = 406 is divisible by 2
  • d3 d4 d5 = 063 is divisible by 3
  • d4 d5 d6 = 635 is divisible by 5
  • d5 d6 d7 = 357 is divisible by 7
  • d6 d7 d8 = 572 is divisible by 11
  • d7 d8 d9 = 728 is divisible by 13
  • d8 d9 d10 = 289 is divisible by 17

Find the sum of all 0 to 9 pandigital numbers with this property.

043.rb

Ziemlich straight-forward und recht schnell.

Problem 44

Find the pair of pentagonal numbers, Pj and Pk, for which their sum and difference is pentagonal and D =|Pk - Pj| is minimised; what is the value of D?

044.rb

Idee: Abstand zwischen Pk und Pk+1 ist 3k+1.

Problem 45

Find the next triangle number (> 40755) that is also pentagonal and hexagonal.

045.rb

Sehr schöne Aufgabe! Idee: Jede hexagonale Zahl ist eine Dreieckszahl, also können die Dreieckszahlen komplett ignoriert werden. Ausserdem ist eine natürliche Zahl n genau dann pentagonal, wenn sqrt(24n+1)+1 eine durch 6 teilbare natürliche Zahl ist.

Problem 46

What is the smallest odd composite that cannot be written as the sum of a prime and twice a square?

046.rb

Problem 47

Find the first four consecutive integers to have four distinct primes factors (each). What is the first of these numbers?

047.rb

Problem 48

Find the last ten digits of the series, 11 + 22 + 33 + ... + 10001000.

048.rb

Idee: In jedem Schritt nur die letzten 10 Ziffern betrachten.

Problem 49

The arithmetic sequence, 1487, 4817, 8147, in which each of the terms increases by 3330, is unusual in two ways: (i) each of the three terms are prime, and, (ii) each of the 4-digit numbers are permutations of one another. (...) There is one other 4-digit increasing sequence. What 12-digit number do you form by concatenating the three terms in this sequence?

049.rb

Schöne Aufgabe!

Problem 50

Which prime, below one-million, can be written as the sum of the most consecutive primes?

050.rb

Problem 51

Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family.

051.rb

Diese Aufgabe hat mir überhaupt nicht gefallen. Das einzige was man hier eventuell lernt ist, wie man Teilmengen/Pattern enumeriert, was aber eigentlich klar ist, wegen der natürlichen Bijektion zwischen Pot(M) und {0,1}|M|. Ein paar Optimierungen: Die Pattern 0...0 und 1...1 braucht man nicht zu betrachten. Außerdem braucht man keine Primzahlen mehr betrachten, die bereits in einer vorherigen Familie von Primzahlen generiert wurden. In dieser Aufgabe verstecken sich einige nervige Stolpersteine, z.B. darf man keine Zahlen mit führenden Nullen betrachten und die ursprüngliche Zahl, die zur Generierung genutzt wurde, muss nicht zwangsweise ein Teil der generierten Menge sein. Insgesamt läuft meine Lösung in etwa 15 Sekunden. Die obere Schranke von 106 war mehr oder weniger geraten.

Problem 52

Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits.

052.rb

Editor auf, Code runtergeschrieben, Editor zu, gestartet, tut.

Problem 53

How many, not necessarily distinct, values of nCr, for 1 <= n <= 100, are greater than one-million?

053.rb

Idee: Dynamische Programmierung und Rekursionsformel benutzen.

Problem 54

The file poker.txt contains one-thousand random hands dealt to two players. Each line of the file contains ten cards (separated by a single space): the first five are Player 1's cards and the last five are Player 2's cards. How many hands does Player 1 win?

054.rb

Lustige Aufgabe... Etwas lange Lösung.

Problem 55

If we take 47, reverse and add, 47 + 74 = 121, which is palindromic. A number that never forms a palindrome through the reverse and add process is called a Lychrel number. (...) every number below ten-thousand, it will either (i) become a palindrome in less than fifty iterations, or, (ii) no one, with all the computing power that exists, has managed so far to map it to a palindrome. How many Lychrel numbers are there below ten-thousand?

055.rb

Problem 56

Considering natural numbers of the form, ab, where a, b < 100, what is the maximum digital sum?

056.rb

Problem 57

In the first one-thousand continued fraction expansions of sqrt(2), how many fractions contain a numerator with more digits than denominator?

057.rb

Etwas tricky drauf zu kommen, aber im Nachhinein relativ simpel.

Problem 58

What is the side length of the square spiral for which the ratio of primes along both diagonals first falls below 10%?

058.rb

Eigentlich eine leichte Aufgabe, aber trotzdem in Ruby recht langsam. Optimierungen, die mir eingefallen sind: Zahlenreihe durch Additionen statt Multiplikationen erzeugen; Letzte Zahl ist ein Quadrat (also nie prim); Nur ungerade Seitenlängen betrachten; ...

Problem 59

A (...) encryption method is to take a text file, (...), then XOR each byte with a given value, taken from a secret key. (...) the encryption key consists of three lower case characters. Using cipher1.txt (...), a file containing the encrypted ASCII codes, and the knowledge that the plain text must contain common English words, decrypt the message and find the sum of the ASCII values in the original text.

059.rb

Nettes Problem. Idee: Mögliche Keys bruteforcen und die Ciphers, deren zugehöriger Plaintext Sonderzeichen und nicht-darstellbare ASCII Zeichen enthält, ignorieren.

Problem 60

Find the lowest sum for a set of five primes for which any two primes concatenate to produce another prime.

060.rb

Mit kleinen Primzahlen anfangen und erstmal nur für jedes p eine möglichst große Liste mit Paaren (p,q1), (p,q2), ..., (p,qk) finden, für die die Bedingung erfüllt ist. Dann mit einer rekursiven Tiefensuche testen welche (qi, qj) aus dieser potentiellen Lösung die Bedingung erfüllen. Sobald wir eine 5 elementige Menge gefunden haben, können wir direkt aufhören. Wegen der Reihenfolge in der getestet wird, ist diese auf jeden Fall die mit der kleinsten Summe. Läuft in etwa 3 Sekunden.

Problem 61

Find the sum of the only ordered set of six cyclic 4-digit numbers for which each polygonal type triangle, square, pentagonal, hexagonal, heptagonal, and octagonal, is represented by a different number in the set.

061.rb

Keine Tricks, einfach (sehr) schmutzig runtergecodet.

Problem 62

Find the smallest cube for which exactly five permutations of its digits are cube.

062.rb

Nicht die schönste Lösung, aber blitzschnell. Idee: Alle Kubikzahlen generieren und jedesmal wenn die Ziffernlänge sich erhöht hat, nachgucken ob wir bereits einen Treffer haben. Die Rechnungen werden in einem Hash gespeichert, dessen Key die "sortierte Zahl" ist (denn das ist offensichtlich eine Normalform für die Bahnen der Zahl unter Permutationen).

Problem 63

How many n-digit positive integers exist which are also an nth power?

063.rb

Tipp: Man rechnet leicht nach, dass die Basis nicht größer als 9 sein darf.

Problem 64

How many continued fractions for N <= 10000 have an odd period?

064.rb

Einen Algorithmus zur Berechnung der Kettenbruchentwicklung von sqrt(N) findet man bei Wikipedia. Für jeden davon bestimmt man die Periodenlänge indem man prüft wann sich eine Konfiguration wiederholt (jeder Wert hängt nur von dem vorherigen ab). Als kleine Optimierung ist mir aufgefallen, dass alle Werte mit ungeraden Periodenlängen immer di-1=1 haben. Ich weiß allerdings nicht wieso (bzw. ob das überhaupt immer stimmt).

Problem 65

Find the sum of digits in the numerator of the 100th convergent of the continued fraction for e.

065.rb

Gähn. :-)

Problem 66

Consider quadratic Diophantine equations of the form: x2 - Dy2 = 1. Find the value of D <= 1000 in minimal solutions of x for which the largest value of x is obtained.

066.rb

Eine interessante Aufgabe mit viel Theorie dahinter, die mich einige Zeit gekostet hat. Glücklicherweise habe ich vor kurzem eine Vorlesung über algebraische Zahlentheorie gehört und habe daher erkannt, dass man hier die sogenannte Grundeinheiten im Ganzheitsring des quadratischen Zahlkörpers Q(sqrt(D)) bestimmen soll. Habe mich dann etwas schlau gemacht und herausgefunden, dass die Lösung des Problems in dem generieren der Kettenbruchapproximationen liegt (sqrt(D) ist irrational falls D kein Quadrat ist und hat daher eine unendliche Kettenbruchentwicklung). Ein paar Links als Anlaufpunkt: Infinite continued fractions, Continued fraction expansion of squares, Pell Gleichung.

Problem 67

Find the maximum total from top to bottom in triangle.txt, a 15K text file containing a triangle with one-hundred rows.

067.rb

Siehe Problem 18.

Problem 69

Find the value of n <= 1,000,000 for which n/phi(n) is a maximum.

069.rb

Erst etwas Brute-Force probiert, dann gemerkt, dass man die Aufgabe recht einfach (sogar ohne Computer) lösen kann. Damit n/phi(n) gross wird, sollte phi(n) klein sein. Bekanntlich ist phi(p)=p-1 und phi zahlentheoretisch. Die korrekte Lösung ist daher phi(2*3*5*7*11*13*17) (Produkt der ersten k Primzahlen, so dass das Produkt kleiner als die gegebene Schranke ist).

Problem 70

Find the value of n, 1<n<107, for which phi(n) is a permutation of n and the ratio n/phi(n) produces a minimum.

070.rb

Nette Aufgabe. Zunächst einmal gilt n/phi(n) = ∏p|n (1+1/(p-1)). Die Exponenten spielen für den zu minimierenden Bruch also keine Rolle und wir konzentrieren uns auf Werte, die wenige, aber dafür sehr große, Primfaktoren haben. Da Primzahlen stets auf 1, 3, 7 oder 9 enden und phi(p)=p-1 gilt (phi(p) sich also nur an der letzten Stelle von p unterscheidet), kann phi(p) niemals eine Permutation von p sein. Als nächstes habe ich Zahlen mit genau zwei Primfaktoren probiert. Da ich davon ausgegangen bin, dass beide Faktoren ziemlich groß sein werden, habe ich auf Faktoren um sqrt(107) beschränkt (mit einem Toleranzfaktor von 3). Das war bereits ausreichend, um die Lösung zu finden. Winzige Optimierung: Permutationen haben die gleiche Quersumme, also auch den gleichen Rest modulo 3; Ich betrachte daher nur Primzahlpaare p,q, für die n - phi(n) = p*q - (p-1)*(q-1) = p+q-1 durch 3 teilbar ist. Läuft in etwa einer Sekunde. Insgesamt eine schöne Aufgabe. Meine Lösung fühlt sich allerdings sehr "heuristisch" und speziell an. Ich bin mir nicht sicher, ob (mit anderen Parametern in der Aufgabenstellung) nicht eine Lösung mit mehr Primfaktoren möglich wäre.

Problem 71

By listing the set of reduced proper fractions n/d for d <= 1,000,000 in ascending order of size, find the numerator of the fraction immediately to the left of 3/7.

071.rb

Lustigerweise habe ich mich genau in dem moment, in dem ich das Problem zum ersten mal gelesen habe, zufälligerweise mit genau diesem Thema beschäftigt (in der Vorlesung Algebraische Zahlentheorie II von Herrn Prof. Krieg an der RWTH Aachen) und wusste daher, dass für zwei aufeinanderfolgende Farey-Brüche a/b und c/d die Beziehung bc-ad=1 gilt. Daher muss für den gesuchten Bruch a/b die Beziehung a = (3b-1)/7 gelten.

Problem 72

How many elements would be contained in the set of reduced proper fractions n/d for d <= 1,000,000?

072.rb

Wenn man ein bisschen etwas über Farey-Brüche weiss, dann ist klar, dass hier die Summe über die Werte der Phi-Funktion gesucht ist. Habe zuerst ewig lange irgendwelche optimierten Brute-Force Varianten ausprobiert (die aber schon für deutlich kleinere Werte von d extrem langsam waren), bis ich zufällig im Netz eine klevere Methode gefunden habe, um eine Wertetabelle der Phi-Funktion aufzustellen (die ganz ähnlich funktioniert wie ein Primzahlsieb und viel schneller ist als der naive Ansatz über den euklidischen Algorithmus).

Problem 73

How many fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for d <= 12,000?

073.rb

Relativ einfach. Brute-Force Idee ist ein O(n2) Algorithmus, der alle Brüche durchläuft. Es geht aber deutlich schneller: Die gekürzten Brüche zwischen 1/3 und 1/2 lassen sich (in Reihenfolge!) durch Farey-Folgen aufzählen. Kennt man zwei aufeinander folgende Terme, so lässt sich der nächste Term leicht berechnen. Dies macht man, beginnend bei 1/3, bis man den Bruch 1/2 erreicht. Man muss also lediglich noch den Startwert, d.h. den Bruch direkt nach 1/3, bestimmen, was aber ebenfalls kein Problem ist, da zwei Brüche a/b, c/d genau dann benachbarte Farey-Brüche (mit max. Nenner n) sind, wenn bc-ad=1 und d <= n < b+d gilt. Mit a/b = 1/3 wählt man für die erste Bedingung c/d = 1/2. Da es sich um eine Linearkombination des ggT=1 handelt, kann man Vielfache von a bzw. b addieren (ohne die erste Bedingung zu verletzen). Um die zweite Bedingung zu erfüllen wählt man floor((n-d)/b) als Vielfaches. Alternativ kann man auch einfach bei 0/1, 1/n starten und entsprechend später anfangen zu zählen (dauert etwa drei- bis viermal so lange).

Problem 74

The number 145 is well known for the property that the sum of the factorial of its digits is equal to 145: (...) How many chains, with a starting number below one million, contain exactly sixty non-repeating terms?

074.rb

Öde. Bruteforce mit etwas Memoization.

Problem 75

(...) Given that L is the length of the wire, for how many values of L <= 1,500,000 can exactly one integer sided right angle triangle be formed?

075.rb

Schöne Aufgabe. Offensichtlich geht es hier um Pythagoreisches Tripel. Die primitiven Tripel (d.h. die (a,b,c) mit ggT(a,b,c)=1) lassen sich effizient enumerieren (siehe Wikipedia). Man wählt n>m mit ggT(n,m)=1 und n,m mit unterschiedlicher Parität, dann durchläuft die Folge (n2-m2, 2mn, n2+m2) alle (primitiven) Tripel (mit Umfang L=2(n2+mn)). Anschließend kann man alle (die primitiven und die nicht-primitiven) via (k*a, k*b, k*c) zählen. Läuft in etwa 2 Sekunden.

Problem 76

How many different ways can one hundred be written as a sum of at least two positive integers?

076.rb

Jeder der schonmal etwas Kombinatorik betrieben hat weiss, dass es hier um die sogenannte Partitionsfunktion geht. Eine explizite Darstellung ist mir nicht bekannt, aber man kann sie relativ leicht rekursiv beschreiben und mit einer Memo Tabelle geht das sogar halbwegs flott. Links: Wolfram MathWorld, Sloans.

Problem 77

What is the first value which can be written as the sum of primes in over five thousand different ways?

077.rb

Dynamic Programming ftw :-)

Problem 78

Let p(n) represent the number of different ways in which n coins can be separated into piles. For example, five coins can separated into piles in exactly seven different ways, so p(5)=7. (...) Find the least value of n for which p(n) is divisible by one million.

078.rb

Offensichtlich ist p die Partitionsfunktion. Diese lässt sich mit Hilfe des Pentagonalzahlsatzes relativ effizient iterativ berechnen (jedenfalls deutlich effizienter als der rekursive Ansatz über p(k,n)), siehe auch den Abschnitt bei Wikipedia über die erzeugende Funktion. Meine Lösung ist leider trotzdem sehr langsam (ca. 40 Sekunden bei mir).

Problem 79

A common security method used for online banking is to ask the user for three random characters from a passcode. The text file, keylog.txt, contains fifty successful login attempts. Given that the three characters are always asked for in order, analyse the file so as to determine the shortest possible secret passcode of unknown length.

079.rb

An dieser Aufgabe bin ich lange verzweifelt bis mein Kollege Johannes die Aufgabe mit Stift und Papier in weniger als einer Minute gelöst hat. Das Prinzip ist natürlich total simpel, man stellt die Daten als gerichteten Graphen dar und macht eine Topologische Sortierung.

Problem 80

For the first one hundred natural numbers, find the total of the digital sums of the first one hundred decimal digits for all the irrational square roots.

080.rb

Okay, das war etwas gecheatet, eigentlich wollte ich die Berechnung der Dezimalentwicklung selber machen (z.B. so wie hier). Stattdessen habe ich es mit der BigDecimal Klasse von Ruby gemacht :-(

Problem 81

(...) the minimal path sum from the top left to the bottom right, by only moving to the right and down (...). Find the minimal path sum, in matrix.txt a 31K text file containing a 80 by 80 matrix, from the top left to the bottom right by only moving right and down.

081.rb

Dynamic Programming, piece of cake ;-)

Problem 82

The minimal path sum (...) by starting in any cell in the left column and finishing in any cell in the right column, and only moving up, down, and right (...). Find the minimal path sum, in matrix.txt (...), containing a 80 by 80 matrix.

082.rb

Etwas schwieriger als Problem 81, aber trotzdem relativ einfach. Die Matrix lässt sich als gewichteter Graph mit |V|=802 Knoten interpretieren und gesucht ist ein kürzester Pfad von einem der Knoten in der ersten Spalte zu einem der Knoten in der letzten Spalte. Mein erster Gedanke war der Dijkstra Algorithmus. Ich war allerdings zu faul eine vernünftige Datenstruktur zur Speicherung der Knoten zu implementieren (und ein normales Array ist zu langsam). Wenn man sich den Graph genauer anguckt sieht man, dass er (fast) azyklisch ist und in solchen Graphen kann man durch topologische Sortierung das Kürzeste-Wege-Problem in Linearzeit lösen. Das habe ich dann im wesentlichen auch gemacht, indem ich die Knoten von "rechts nach links" durchgegangen bin. Einen deutlichen Speedup gab es dann noch durch die Beobachtung, dass es genügt sich nur die Kosten für die letzten zwei Spalten zu merken anstatt für alle Knoten. Der Algorithmus läuft in O(n3) = O(|V| * sqrt(|V|)) und braucht bei mir etwa 2 Sekunden. (Zum Vergleich: Mit Dijkstra brauchte ich etwa doppelt soviele Codezeilen, eine Laufzeit von O(n4) und etwa 120 Sekunden.)

Problem 85

By counting carefully it can be seen that a rectangular grid measuring 3 by 2 contains eighteen rectangles: (...) Although there exists no rectangular grid that contains exactly two million rectangles, find the area of the grid with the nearest solution.

085.rb

Ganz nett. Der naive Ansatz ist eine vierfach verschachtelte Schleife, die im Rumpf einen Counter hochzählt. Wenn man das mal als (vierfach) Summe aufschreibt und eine Weile vereinfacht, sieht man sehr leicht, dass es genau h(h+1)w(w+1)/4 Rechtecke in einem Gitter von Breite w und Höhe h gibt. Breiter als w = 2000 muss man nicht testen, denn damit ist man mit Höhe h = 1 bereits zu groß (und ich habe erwartet, dass es "besser" als mit h=1 geht). Außerdem reicht es aus Symmetriegründen wenn man h<w testet.

Problem 87

How many numbers below fifty million can be expressed as the sum of a prime square, prime cube, and prime fourth power?

087.rb

Ziemlich einfach. Brute Force, mit der Beobachtung, dass nur Primzahlen bis √(50*106 - 23 - 24) betrachtet werden müssen.

Problem 92

How many numbers below 10.000.000 are not happy?

092.rb

Schöne Aufgabe eigentlich. Leider ist meine Lösung extrem langsam. Im wesentlichen Brute Force mit zwei Memo-Tables. Winzige Optimierung: Die Tabelle muss nur bis maximal 567 gehen, denn das ist die größtmögliche Zahl, die erreicht werden kann.

Problem 95

(...) Find the smallest member of the longest amicable chain with no element exceeding one million.

095.rb

Hier geht's um Sociable Numbers. Relativ straight-forward: Die erste Doppelschleife generiert die Teilersummen (ca. 1/3 der Laufzeit), der zweite Teil generiert alle Ketten.

Problem 96

The 6K text file, sudoku.txt, contains fifty different Su Doku puzzles ranging in difficulty, but all with unique solutions (...). By solving all fifty puzzles find the sum of the 3-digit numbers found in the top left corner of each solution grid.

096.rb

Diese Aufgabe stand schon lange auf meiner TODO Liste, außerdem wollte ich sowieso schon immer mal einen Sudoku Solver schreiben. Eigentlich sehr straight-forward, hat mich trotzdem ca. 2 Stunden gekostet weil ich zu wenig Ahnung von Ruby's call-by-reference Prinzip habe, grml. Für einige der Puzzle ist ein "guess-and-check" Backtracking notwendig. Einen kleinen Speedup kriegt man durch die Heuristik als erstes dort zu "raten" wo wenig Wahlmöglichkeiten bestehen. Die 50 Sudokus werden in etwa 10 Sekunden gelöst bei mir.

Problem 97

In 2004 there was found a massive non-Mersenne prime which contains 2,357,207 digits: 28433 * 27830457+1. Find the last ten digits of this prime number.

097.rb

Schöne Aufgabe! Idee: Große Schritte machen und in jedem schon nur mit den letzten 10 Stellen rechnen.

Problem 98

By replacing each of the letters in the word CARE with 1, 2, 9, and 6 respectively, we form a square number: 1296 = 362. What is remarkable is that, by using the same digital substitutions, the anagram, RACE, also forms a square number: 9216 = 962. We shall call CARE (and RACE) a square anagram word pair and specify further that leading zeroes are not permitted, neither may a different letter have the same digital value as another letter. Using words.txt, a 16K text file containing nearly two-thousand common English words, find all the square anagram word pairs (a palindromic word is NOT considered to be an anagram of itself). What is the largest square number formed by any member of such a pair?

098.rb

Hier gibt es ein paar Kleinigkeiten, die man leicht übersieht. Erst einmal fällt auf, dass wir nur Wörter betrachten müssen, für die in der Liste überhaupt ein Anagramm existiert. Alle anderen können wir ignorieren. Meine erste Idee war: Für jedes Wortpaar über alle Substitutionen iterieren und testen ob beide Wörter unter der gleichen Substitution jeweils auf ein Quadrat abgebildet werden. Das funktioniert, aber ist sehr langsam (ca. 5 Minuten). Effizienter ist es, alle Quadrate zu generieren (als obere Grenze kann man 10n nehmen wobei n die Länge des längsten Wortes aus der Liste ist, für das ein Anagramm existiert (n=9)). Auch hier löscht man alle Quadrate, für die kein Anagramm existiert. Als nächstes testet man für jedes Quadrat und jedes Wort (mit gleicher Länge), ob die dadurch induzierte Abbildung das zweite Wort auf ein Anagramm des ersten Quadrates abbildet. Es dürfen nur (Quadrat,Wort)-Paare betrachtet werden, die injektive Abbildungen induzieren. Kompliziert beschrieben, aber die Idee ist eigentlich einfach :-) Läuft bei mir in unter 5 Sekunden.

Problem 99

Using base_exp.txt, a 22K text file containing one thousand lines with a base/exponent pair on each line, determine which line number has the greatest numerical value.

099.rb

Sehr einfach. Vergleiche die Logarithmen statt den Werten...

Problem 100

If a box contains twenty-one coloured discs, composed of fifteen blue discs and six red discs, and two discs were taken at random, it can be seen that the probability of taking two blue discs, P(BB) = (15/21)(14/20) = 1/2. (...) By finding the first arrangement to contain over 1012 = 1,000,000,000,000 discs in total, determine the number of blue discs that the box would contain.

100.rb

Sehr interessante Aufgabe. Es ist P(BB) = (a/b)*((a-1)/(b-1)) = (a/(a+l))*((a-1)/(a+l-1)) wobei a die Anzahl der blauen und b=a+l die Anzahl der roten Discs ist. Die Wahrscheinlichkeit soll genau 1/2 sein. Mit etwas umformen erhält man 2a(a-1) = (a+l)(a+l-1). Noch etwas mehr umformen und PQ-Formel ergibt, dass 1+8l2 ein Quadrat sein muss, d.h. es gibt ein y mit y2 = 1 + 8l2, oder anders: y2-8l2 = 1. Dies ist eine Pellsche Gleichung, welche man über die Kettenbruchentwicklung von sqrt(8) lösen kann. Die Lösungen (a,b) nennt man übrigens Diophantische Paare.

Problem 102

Using triangles.txt, a 27K text file containing the co-ordinates of one thousand "random" triangles, find the number of triangles for which the interior contains the origin.

102.rb

Piece of cake. Bisschen analytische Geometrie aus der Oberstufe :-) Man kann das Dreieck durch ein Gleichungssystem beschreiben: x = u + av + bw. Man setzt x=(0,0) und löst nach a und b. Wenn a,b>0 und a+b<1 gilt, dann ist der Punkt im Dreieck.

Problem 104

Given that Fk is the first Fibonacci number for which the first nine digits AND the last nine digits are 1-9 pandigital (contain all the digits 1 to 9, but not necessarily in order), find k.

104.rb

Eine recht schwere Aufgabe. Das gesuchte k ist relativ gross und die zugehörige k-te Fibonacci Zahl hat mehrere tausend Stellen. Idee: Erzeuge nicht die Fibonacci Folge sondern die Folge der letzten und vorderen 9 Ziffern jedes Folgengliedes.

Problem 108

In the following equation x, y, and n are positive integers: 1/x + 1/y = 1/n. What is the least value of n for which the number of distinct solutions exceeds one-thousand?

108.rb

Einfachere Version von 110, siehe unten. Gleicher Code.

Problem 110

In the following equation x, y, and n are positive integers: 1/x + 1/y = 1/n. What is the least value of n for which the number of distinct solutions exceeds four million?

110.rb

Eine der Aufgaben, die mir am besten gefallen hat, auch wenn ich erst einige Stunden an einem dämlichen Bruteforce Algorithmus mit minimalen Optimierungen vergeudet habe, bevor ich angefangen habe nachzudenken. Es handelt sich hier um eine diophantische Gleichung und durch ein paar elementare Umformungen sieht man, dass nx+ny=xy gelten muss, was äquivalent zu n2=(x-n)(y-n)=:XY ist. Die tatsächlichen Werte der Lösungen sind unwichtig, es geht nur um die Anzahl. d(n2) bezeichnet die Anzahl der positiven Teiler von n2. Da für jedes (x,y) auch (y,x) eine Lösung ist, werden hier alle Lösungen (außer x=y, d.h. (x,y)=(2n,2n)) doppelt gezählt. Tatsächlich interessiert uns also (d(n2)+1)/2. Für n2 = p12e1 * ... * pk2ek ist d(n2) = (2e1+1) * ... * (2ek+1). Gesucht ist also das kleinste Quadrat, dessen Teileranzahl größer als 4*106 ist. Die Lösung hat sehr ähnliche Eigenschaften wie sogenannte hochzusammengesetzte Zahlen, d.h. dass e1 >= ... >= ek gilt und die k Primzahlen genau die ersten k Primzahlen sind (wäre es anders, so könnte man umordnen bzw. Faktoren austauschen um eine kleinere Lösung mit der gleichen Teileranzahl zu bekommen; Man beachte, dass die Primzahlen selbst in d(n2) nicht vorkommen, nur die Exponenten). Da das Produkt der ersten 14 Primzahlen bereits mehr als 4*106 Teiler hat, ist k höchstens 14. Als Heuristik habe ich daher 13, 12, 11, ... ausprobiert, d.h. nur Lösungskandidaten betrachtet, die Vielfache der ersten 13, 12, 11, ... Primzahlen sind (und diese Idee bringt auch den größten Speed-up, da der Lösungsraum extrem eingeschränkt wird). Mit einer vereinfachten Probedivision (nur die ersten 14 Primzahlen testen) habe ich dann die Exponenten e1, ..., ek bestimmt um die Teileranzahlen zu bestimmen. Das Programm läuft in weniger als einer halben Sekunde.

Problem 112

(...) We shall call a positive integer that is neither increasing nor decreasing a "bouncy" number. (...) Find the least number for which the proportion of bouncy numbers (below) is exactly 99%.

112.rb

Langweilige Aufgabe, langweilige (und langsame) Lösung. Läuft in etwas unter 10 Sekunden.

Problem 119

The number 512 is interesting because it is equal to the sum of its digits raised to some power: 5 + 1 + 2 = 8, and 83 = 512. Another example of a number with this property is 614656 = 284. We shall define an to be the n-th term of this sequence and insist that a number must contain at least two digits to have a sum. You are given that a2 = 512 and a10 = 614656. Find a30.

119.rb

Erste Idee: Zahlen der Reihe nach durchlaufen und dann die passende Potenz dazu finden (viel zu langsam). Zweite Idee: Testen ob der Logarithmus zur Quersumme als Basis ganzzahlig ist (viel zu langsam). Dritte (gute) Idee: Alle Potenzen generieren und dann die rausfischen, die die gewünschte Eigenschaft haben (sehr schnell :-)).

Problem 120

Let r be the remainder when (a-1)n + (a+1)n is divided by a2. (...) as n varies, so too will r, but for a = 7 it turns out that rmax = 42. For 3 <= a <= 1000, find the sum of all the rmax.

120.rb

Recht einfach, wenn man Aufgabe 123 vorher schon gemacht hat.

Problem 123

Let pn be the n-th prime (...) and let r be the remainder when (pn-1)n + (pn+1)n is divided by pn2. Find the least value of n for which the remainder first exceeds 1010.

123.rb

Nette Aufgabe. Mit dem Binomischen Lehrsatz lassen sich die beiden Potenzen ausschreiben, anschließend kann man zusammenfassen und man sieht, dass modulo pn2 fast alle Summanden gleich Null sind und sich der ganze Term zu 2 * n * pn vereinfacht, falls n ungerade ist, und zu 2, falls n gerade ist.

Problem 124

The radical of n, rad(n), is the product of distinct prime factors of n. If we calculate rad(n) (...), then sort them on rad(n), and sorting on n if the radical values are equal (...). Let E(k) be the kth element in the sorted n column (...). If rad(n) is sorted for 1 <= n <= 100000, find E(10000).

124.rb

Im Grunde ein einfaches Primzahlsieb, dass sich bereits während des Aufbaus die Primfaktoren merkt. Läuft in etwa 3 Sekunden.

Problem 125

Find the sum of all the numbers less than 108 that are both palindromic and can be written as the sum of consecutive squares.

125.rb

Aus der bekannten Formel für die Summe der ersten n Quadrate, kann man leicht eine Formel ableiten für die Summe der Quadrate von k bis n. Vorsicht: Die Darstellung einer Zahl als Summe aufeinanderfolgender Quadrate ist nicht eindeutig (d.h. man muss aufpassen, dass man keine Zahl doppelt zählt).

Problem 127

The radical of n, rad(n), is the product of distinct prime factors of n. We shall define the triplet of positive integers (a,b,c) to be an abc-hit if: GCD(a, b) = GCD(a, c) = GCD(b, c) = 1, a < b, a + b = c, rad(abc) < c. Find ∑ c for c < 120000.

127.rb

Dies ist eine deutlich schwierigere Variante von Problem 124 (und offensichtlich motiviert durch die berühmte abc-Vermutung aus der elementaren Zahlentheorie), mit einer Menge Optimierungen. Zunächst einmal gilt rad(abc)=rad(a)rad(b)rad(c) wenn a,b,c paarweise teilerfremd sind (es genügt also bis cmax=120000 zu sieben). Die aller wichtigste Idee ist, dass man die a-Werte in der Reihenfolge ihrer Radikale durchläuft (also quasi die sortierte Liste aus Problem 124 benutzt) und abbricht sobald rad(a)rad(c) >= c auftritt (denn dies gilt dann für alle weiteren a-Werte ebenfalls). Weiterhin muss a<c/2 gelten (wegen a<b=c-a). Teilerfremdheit kann man leicht testen, da wir ja sowieso alle Zahlen im Sieb von Problem 124 bereits faktorisiert haben. Für quadratfreie (und insbesondere prime) Werte c gilt schon rad(c)=c, also können diese komplett ignoriert werden. Außerdem kann man noch nutzen, dass rad(a)rad(c) < c/2 gelten muss (statt nur < c), denn rad(a) und rad(b) können nicht beide kleiner als 2 sein. Insgesamt läuft das Programm in etwa 20 Sekunden.

Problem 131

There are some prime values, p, for which there exists a positive integer, n, such that the expression n3 + p * n2 is a perfect cube. How many primes below one million have this remarkable property?

131.rb

Sehr schöne Aufgabe. Der Brute-Force Ansatz lässt sich zwar etwas optimieren, aber dauert trotzdem noch mehrere Minuten. Schöner: n2 * (n + p) ist aufjedenfall eine Kubikzahl, wenn sowohl n als auch n+p welche sind (etwa n = m3). Wenn dies der Fall ist, ist p die Differenz zweier Kubikzahlen (p = (n+p) - n). Die Differenz zweier Kubikzahlen faktorisiert aber zu a3 - b3 = (a-b)(a2 + ab + b2), d.h. es muss a=b+1 gelten (also p = (m+1)3 - m3). Die Primzahl p ist also die Differenz zweier aufeinander folgender Kubikzahlen (solche Primzahlen nennt man übrigens Cuban Primes).

Problem 132

A number consisting entirely of ones is called a repunit. We shall define R(k) to be a repunit of length k. (...) Find the sum of the first forty prime factors of R(109).

132.rb

Es gilt R(k) = (10k - 1)/9, d.h. p teilt R(k) gdw. (10k-1)/9 = 0 mod p. Weil p prim ist, ist das äquivalent zu 10k = 1 mod p. Für k = 109 testen wir einfach die Primzahlen bis wir 40 Stück gefunden haben (2, 3, und 5 nicht mit testen. 2 und 5 sind ausgeschlossen, weil R(k) nicht mit 0 endet und 3 ist ausgeschlossen, weil 109 nicht durch 3 teilbar ist).

Problem 133

A number consisting entirely of ones is called a repunit. We shall define R(k) to be a repunit of length k. (...) Find the sum of all the primes below one-hundred thousand that will never be a factor of R(10n).

133.rb

Sehr ähnlich zur vorherigen Aufgabe. Entscheidend ist die Beobachtung, dass R(b) nur durch R(a) teilbar sein kann, wenn b durch a teilbar ist. Weil 10n immer durch 10m teilbar ist falls m<n, genügt es, wenn wir einfach für irgendein großes n (z.B. 50) die Teilbarkeit wie in Problem 132 testen.

Problem 135

Given the positive integers, x, y, and z, are consecutive terms of an arithmetic progression, the least value of the positive integer, n, for which the equation, x2 - y2 - z2 = n, has exactly two solutions is n = 27. (...) How many values of n less than one million have exactly ten distinct solutions?

135.rb

x,y,z sind positiv und aufeinanderfolgende Glieder einer arithmetischen Folge, d.h. x=z+2a, y=z+a. Da x > y > z > 0 ist auch a > 0. (z+2a)2 - (z+a)2 - z2 = n lässt sich schreiben als n = (3a-z)(a+z). Man kann nun einfach im Brute-Force-Stil über a,z iterieren und alle n generieren und anschliessend zählen wieviele n genau 10 mal vorkommen. Als kleine Optimierung: Da n positiv ist und 3a-z <= n gilt, muss z <= 3a <= n+z <= 2n gelten. Code läuft in unter 10 Sekunden.

Problem 136

The positive integers, x, y, and z, are consecutive terms of an arithmetic progression. Given that n is a positive integer, the equation, x2 - y2 - z2 = n, has exactly one solution when n = 20. (...) How many values of n less than fifty million have exactly one solution?

136.rb

Dies ist ehrlich gesagt nicht meine Lösung. Ich habe zuerst meine Lösung für Problem 135 modifiziert, welche ca. 10 Minuten für Problem 136 benötigte. Im Forum zu diesem Problem habe ich dann einen sehr kleveren Ansatz gefunden. Man schreibt x = y+a und z=y-a und ähnlich wie bei Problem 135 erhält man n=y(4a-y), d.h. n=yk mit y+k = 0 (mod 4). Der entscheidene Unterschied zu Problem 135 ist, dass wir an n interessiert sind, für die eine eindeutige Lösung existiert. Man kann zeigen, dass dies genau dann der Fall ist, wenn n = 4, 16, 4p, 16p, q gilt, wobei p>2 prim und q prim mit q=3 (mod 4) ist. Der Beweis dazu findet sich ebenfalls im Forum. Der Code läuft bei mir in etwa einer Minute.

Problem 142

Find the smallest x + y + z with integers x > y > z > 0 such that x+y, x-y, x+z, x-z, y+z, y-z are all perfect squares.

142.rb

Idee: Nicht x,y,z suchen und testen ob die Werte Quadrate sind sondern die Quadrate direkt generieren. Man schreibt a=x+y, b=x-y, c=x+z, d=x-z, e=y+z, f=y-z. Dann gilt f=a-c, e=a-d und b=c-e, d.h. wir müssen nur die Quadrate a, c und d generieren. Ob f, e und b dann auch Quadrate sind testen wir. Anschließend kann man x=(a+b)/2, y=(e+f)/2 und z=(c-d)/2 nutzen um die Summe zu berechnen. Noch eine Optimierung: Damit x,y,z ganze Zahlen sind, kann man die Loops in Zweierschritten laufen lassen und zwar so, dass a+b=c+d gerade ist (d.h. c und d beide gerade oder beide ungerade).

Problem 169

Define f(0)=1 and f(n) to be the number of different ways n can be expressed as a sum of integer powers of 2 using each power no more than twice.

169.rb

Interessante Aufgabe. Ich hatte sie schon länger im Hinterkopf, aber habe nie wirklich drüber nachgedacht. Irgendwann bin ich durch Zufall auf den Calkin-Wilf Tree gestoßen: Ein Baum, der genau die rationalen Zahlen als Knoten enthält. Eine Breitensuche durch diesen Baum enumeriert (ohne Wiederholung!) alle rationalen Zahlen. Betrachtet man die Folge der Nenner, so erhält man erstaunlicherweise genau die Funktion f aus der Aufgabe. Die sehr einfache Rekursionsformel wird bei Wikipedia erwähnt.

Problem 179

Find the number of integers 1 < n < 107, for which n and n+1 have the same number of positive divisors.

179.rb

Der naive Ansatz ist eine Abwandlung eines Primzahlsiebs: for(skip=1; skip<n; skip++) for(j=0; j<n; j+=skip) div[j]++;. Das läuft bei mir (in Ruby) in etwa 4 Minuten (ich denke es ist in erster Linie so langsam weil das Speicherzugriffsmuster dieses Algorithmus sehr sehr schlecht ist und daher nie lange Zeit Daten im Cache bleiben). Meine Lösung nutzt etwas mehr Zahlentheorie, nämlich dass d(n) = (e1+1) * ... * (ek+1) ist wobei ei die Exponenten aus der Primfaktorzerlegung sind. Daraus folgt dann, dass d(n) = d(n/pe) * (e+1) ist wenn n durch die Primzahl p teilbar ist. Im Primzahlsieb merkt man sich für jede zusammengesetzte Zahl die kleinste Primzahl, die diese teilt. Der Code läuft bei mir in etwa 40 Sekunden. Schneller habe ich es leider nicht hingekriegt :-(

Problem 182

The RSA encryption is based on the following procedure: (...) Choose p=1009 and q=3643. Find the sum of all values of e, 1 < e < phi(1009,3643) and gcd(e,phi)=1, so that the number of unconcealed messages for this value of e is at a minimum.

182.rb

Sehr schöne Aufgabe. Wer den chinesischen Restsatz und die Isomorphie zwischen Zn und ZpxZq kennt, dem ist klar, dass jede RSA Funktion stets nicht-triviale Fixpunkte hat. Tatsächlich kann es passieren, dass eine RSA Funktion keine einzige Nachricht verschlüsselt, d.h. jeder Punkt ist ein Fixpunkt. Die Anzahl der Fixpunkte ist (1+gcd(e-1,p-1))*(1+gcd(e-1,q-1)). Da p,q prim sind, sind p-1 und q-1 stets gerade, d.h. jede RSA Funktion hat mindestens (1+2)*(1+2)=9 Fixpunkte. Wir suchen also die Summe der Werte von e für die genau 9 Fixpunkte existieren. Relativ klar zu implementieren, wenn man diesen Zusammenhang kennt. Eine kleine Optimierung (die auf der Wahl von p und q basiert, d.h. für andere Werte wäre diese Optimierung nicht möglich): p-1 ist durch 4 teilbar, q-1 durch 2, aber nicht durch 4. Daraus folgt, dass e-1 ebenfalls durch 2, aber nicht durch 4 teilbar sein darf, d.h. e mod 4 = 3. Analog ist q-1 durch 3 teilbar, also darf e-1 nicht auch durch 3 teilbar sein (sonst wäre der ggT größer als 2). e darf mit dem gleichen Argument nicht durch 3 teilbar sein (sonst wäre der ggT zu phi größer als 1), also muss e mod 3 = 2 sein. Insgesamt (mit chinesischem Restsatz, da 3 und 4 teilerfremd sind) erhält man e mod 12 = 11, d.h. wir können die Schleife bei 11 beginnen und in 12er Schritten durchlaufen. Laufzeit ist auf meinem Rechner etwa 5 Sekunden. Würde man noch weitere Faktoren von p-1 und q-1 mit einbeziehen (7 und 607), könnte man dies noch drastisch reduzieren.

Problem 183

Let N be a positive integer and let N be split into k equal parts, r = N/k, so that N = r + r + ... + r. Let P be the product of these parts, P = r × r × ... × r = rk. (...) Let M(N) = Pmax for a given value of N. (...) Let D(N) = N if M(N) is a non-terminating decimal and D(N) = -N if M(N) is a terminating decimal. (...) Find ∑ D(N) for 5 <= N <= 10000.

183.rb

Deutlich einfacher als ich auf den ersten Blick angenommen habe :-) Durch ableiten sieht man, dass für reelle Argumente das Maximum bei k=N/e angenommen wird. Meine Vermutung war also, dass ceil(N/e) oder floor(N/e) das Maximum für ganzzahlige k sein wird. Also immer beide ausprobieren und das größere nehmen. Als Optimierung: k*log(n/k) und (n/k)k haben die gleichen Maxima (aber ersteres ist schneller zu berechnen). Um D(N) zu bestimmen reicht es den (vollständig gekürzten!) Nenner von (n/k)k zu betrachten. Enthält dieser andere Primfaktoren als 2 und 5 so ist die Dezimalentwicklung unendlich. Da dieser Nenner im wesentlichen kk ist (bis auf gemeinsame Faktoren mit n) und kk die gleichen Primfaktoren wie k hat, reicht es also k zu betrachten. Das Programm läuft in weniger als 10ms. (Kleine Stolperfalle: e muss hinreichend gut approximiert sein!)

Problem 185

The game Number Mind is a variant of the well known game Master Mind. Instead of coloured pegs, you have to guess a secret sequence of digits. After each guess you're only told in how many places you've guessed the correct digit. So, if the sequence was 1234 and you guessed 2036, you'd be told that you have one correct digit; however, you would NOT be told that you also have another digit in the wrong place. Based on the following guesses, (...), find the unique 16-digit secret sequence.

185.rb

Habe etwas gemogelt. Das Problem lässt sich sehr einfach als (binäres) ILP modellieren (Variable xij = 1 gdw. an Stelle i steht Ziffer j. Natürliche Constraints (pro Stelle genau eine Ziffer, etc.) kodieren und Guesses darstellen, alles relativ straight-forward). Ich habe das Problem dann mit dem GNU lp_solve Tool gelöst.

Problem 187

How many composite integers, n < 108, have precisely two, not necessarily distinct, prime factors?

187.rb

Brute-Force Lösung. Der eigentliche Algorithmus ist recht schnell, aber mein Primzahlsieb ist leider viel zu langsam. Dauert knapp eine Minute. Zum Zählalgorithmus: Entscheidend ist die Beobachtung, dass für jede Semiprimzahl n=pq mit p <= q stets p <= sqrt(n) ist.

Problem 188

Find the last 8 digits of 1777 ↑ ↑ 1855.

188.rb

Es geht hier um sogenannte Potenztürme, oder auch Tetration genannt. Da ich Problem 282 zuerst gelöst hatte, war diese Aufgabe in wenigen Minuten gelöst. Die Idee ist, dass sich die Potenztürme, ganz analog zu normalen Potenzen, nach dem Satz von Euler im Exponenten modulo phi(108) reduzieren lassen (1777 ist prim und damit teilerfremd zu 108). Außerdem kann man zeigen, dass Potenzturmfolgen modulo n stets konstant werden. Es reicht also so weit zu berechnen bis sich ein Wert wiederholt (was relativ schnell passiert).

Problem 197

Given is the function f(x) = [230.403243784 - x2] * 10-9, the sequence un is defined by u0 = -1 and un+1 = f(un). Find un + un+1 for n = 1012. Give your answer with 9 digits after the decimal point.

197.rb

Sehr langweilige Aufgabe.. Wie viele andere vermutlich auch hatte ich eine Art von fraktalem und "chaotischem" Verhalten erwartet. Man sieht aber (durch ausprobieren) leicht, dass die Folge recht schnell (ab ca. 500 Iterationen) um zwei Werte oszilliert (und die Summe von aufeinanderfolgenden Folgengliedern damit konvergiert (und die ersten 9 Stellen sich nichtmehr ändern)).

Problem 203

Find the sum of the distinct squarefree numbers in the first 51 rows of Pascal's triangle.

203.rb

Viel zu einfach für ein Level 5 Problem.

Problem 204

(...) We will call a positive number a generalised Hamming number of type n, if it has no prime factor larger than n. (...) How many generalised Hamming numbers of type 100 are there which don't exceed 109?

204.rb

Man soll hier die Anzahl der Zahlen m <= 109, die 100-glatt sind, bestimmen. Im Grunde macht man eine Art Tiefensuche durch den Baum der Multiplikationsfunktion mit Primzahlen p < 100. Zwei kleine Optimierungen: Man kann mit den Logarithmen rechnen statt mit den Primzahlen selbst, dann tauscht man die Multiplikationen großer Zahlen durch die Addition von Floats. Weiterhin braucht man keine Primzahlen q > p testen falls das Produkt mit p bereits zu groß war (d.h. man kann viele Äste in dem Baum "abschneiden"). Laufzeit bei mir etwa 10 Sekunden.

Problem 205

Peter has nine four-sided (pyramidal) dice, each with faces numbered 1, 2, 3, 4. Colin has six six-sided (cubic) dice, each with faces numbered 1, 2, 3, 4, 5, 6. Peter and Colin roll their dice and compare totals: the highest total wins. The result is a draw if the totals are equal. What is the probability that Pyramidal Pete beats Cubic Colin? Give your answer rounded to seven decimal places in the form 0.abcdefg

205.rb

Hässliche Lösung, aber ziemlich straight-forward. Einfach alle 49 Möglichkeiten für Peter und alle 66 Möglichkeiten für Colin aufzählen und merken wie oft welche Summe (maximal 36) auftrat.

Problem 206

Find the unique positive integer whose square has the form 1_2_3_4_5_6_7_8_9_0, where each "_" is a single digit.

206.rb

Schöne Aufgabe, einfache Lösung. Die Zahl endet mit 0, ist also durch 10 teilbar. Da es sich um ein Quadrat handelt (und 10 quadratfrei ist) muss auch die Wurzel durch 10 teilbar sein, also die Zahl selbst sogar durch 100, d.h. auch die vorletzte Ziffer muss eine 0 sein, die letzten zwei Ziffern können also ignoriert werden, damit ist die letzte relevante Ziffer eine 9. Eine Zahl, deren Quadrat als letzte Ziffer eine 9 hat, muss als letzte Ziffer eine 3 oder eine 7 haben (sieht man an der Rechnung modulo 10), in jedem Fall ist unsere gesuchte Wurzel also ungerade. Die größtmögliche Wurzel ist also 138902663. Von hier aus testen wir abwärts in Zweierschritten, ob wir eine Lösung gefunden haben (und multiplizieren diese anschließend mit 10).

Problem 216

Consider numbers t(n) of the form t(n) = 2n2-1 with n > 1. (...) How many numbers t(n) are prime for n <= 50,000,000?

216.rb

Eine sehr anspruchsvolle Aufgabe. Meine Lösung benötigt etwa 15 Minuten (das Primzahlsieb alleine dauert bereits über eine Minute) und ich bekomme sie leider nicht schneller. Ich schiebe das aber mal auf Ruby, denn in C läuft der gleiche Algorithmus in unter 10 Sekunden. Offensichtlich kann man nicht für jede der 50 Millionen Zahlen einen Primzahltest machen. Auch ein Primzahlsieb bis 2*(5*107)2-1 =~ 5*1015 ist natürlich nicht drin. Die Idee ist: Falls t(n) zusammengesetzt ist, d.h. falls ein p existiert so dass 2n2-1 durch p teilbar ist, so ist 2n2-1=0 mod p. Das kann man umformen zu n2 = (p+1)/2 mod p. Damit t(n) zusammengesetzt ist, muss (p+1)/2 also ein quadratischer Rest modulo p sein mit diskreter Wurzel n. Die Idee ist nun, einfach für alle Werte von p < sqrt(2n2-1) jeweils die beiden Wurzeln zu berechnen. Dies geht mit dem Tonelli-Shanks-Algorithmus. Ein paar kleine Optimierungen: Wir brauchen nur Primzahlen betrachten, die kongruent 1 oder 7 modulo 8 sind, denn nur für diese ist (p+1)/2 ein quadratischer Rest modulo p (sieht man an der Definition vom Legendre Symbol). Anstatt die Wurzeln von (p+1)/2 = 2-1 mod p zu bestimmen kann man auch die von 2 bestimmen, es gilt nämlich (2n)2=2 mod p. Hat man die beiden Wurzeln n1,2 gefunden (mit n2 = p - n1) so weiß man, dass t(ni + kp) ebenfalls alle zusammengesetzt sind, denn auch die sind durch p teilbar. Einzige Ausnahme ist der Fall, dass (p+1)/2 = n2 ist (d.h. t(n)=p). Im Project Euler Forum zu diesem Problem hat übrigens auch niemand einen wirklich besseren Algorithmus (und ich habe keine einzige Ruby Lösung gesehen).

Problem 271

For a positive number n, define S(n) as the sum of the integers x, for which 1 < x < n and x3 = 1 (mod n). (...) Find S(13082761331670030).

271.rb

Relativ einfach für eine so hohe Nummer. Man zerlegt n in Primfaktoren (n ist quadratfrei!) und löst die Gleichung modulo jeder Primzahl (da hat sie dann jeweils maximal 3 Lösungen). Insgesamt ergeben sich dadurch 729 Kombinationen, die man mit dem chinesischen Restsatz nur noch zusammensetzen und addieren muss.

Problem 273

(...) We call S(N) the sum of the values of a of all solutions of a2 + b2 = N, 0 <= a <= b, a, b and N integer. (...) Find S(N), for all squarefree N only divisible by primes of the form 4k+1 with 4k+1 < 150.

273.rb

Schöne Aufgabe mit viel Theorie. Habe eine Weile gebraucht bis es in unter einer Minute lief :-) Als erstes sollte man sich fragen warum in der Aufgabe nur Primzahlen p=4k+1 betrachtet werden sollen, dabei stößt man dann auf den Zwei-Quadrate-Satz von Fermat. Interessant ist auch die Sum of Squares Function. Erst einmal sollte man wissen, dass eine natürliche Zahl N genau dann eine Darstellung als Summe zweier Quadrate hat, wenn die Primfaktoren p=4k+3 von N alle in gerader Anzahl vorkommen. Bei uns ist die Anzahl 0, denn es kommen nur p=4k+1 vor. Damit wissen wir also, dass jedes N mindestes eine solche Darstellung hat. In der Tat gibt es für quadratfreies N genau 2m viele (bis auf Reihenfolge und Vorzeichen), wobei m die Anzahl der Primfaktoren ist. Für 4k+1<150 ist m<16, d.h. wir betrachten 216 verschiedene Zahlen N die jeweils bis zu 216 Darstellungen haben (mit jedem Primfaktor verdoppelt sich die Anzahl). Um die Lösungen zu enumerieren nutzt man die Identität von Brahmagupta-Fibonacci: (a2+b2)(c2+d2)=(ac-bd)2+(ad+bc)2=(ac+bd)2+(ad-bc)2. Es genügt daher die Darstellungen für die Primzahlen zu bruteforcen (davon gibt es jeweils nur eine), und für alle zusammengesetzten N die Darstellungen der Primfaktoren mithilfe dieser Identität zu kombinieren. Dass dies bereits alle Darstellungen sind sieht man mit etwas algebraischer Zahlentheorie daran, dass der Ring der Gausschen Zahlen ein faktorieller Ring ist (d.h. eindeutige Primelementzerlegung; und die beiden Faktoren von 4k+1 = p = a2+b2 = (a+bi)(a-bi) sind prim in Z[i]). Der Algorithmus läuft in etwa 40 Sekunden. Habe ihn auf verschiedene Arten implementiert, aber eine stupide Rekursion ist effizienter als dynamische Programmierung oder Memoization, obwohl dieses Problem eigentlich geeignet für dynamische Programmierung sein sollte.

Problem 282

(...) the Ackermann function A(m, n) is defined as follows (...). Find ∑6n=0 A(n, n) and give your answer mod 148.

282.rb

Sehr schöne Aufgabe, an der ich mir einige Tage die Zähne ausgebissen habe. Die Ackermannfunktion ist bekannt als das Standardbeispiel für nicht primitiv-rekursive Funktionen und sie wächst extrem schnell. Wichtig an dieser Aufgabe ist, dass man die Lösung modulo 148 berechnen soll. Ein direktes Berechnen ist nicht möglich, da bereits A(4,4) viel zu groß ist. Mein erster Ansatz war die Lösung modulo 28 und modulo 78 zu berechnen und anschließend mit dem chinesischen Restsatz zusammenzusetzen. Vorteil ist, dass 2 (die Basis der Potenztürme der Ackermannfunktion) teilerfremd zu 78 ist und man daher den Satz von Euler benutzen kann um die Exponenten in A(4,n) modulo phi(78) zu reduzieren. Das war allerdings nicht nötig. Stattdessen habe ich Carmichael's Lambda Funktion benutzt (welche, was mir auch neu war, im Gegensatz zur eulerschen Phi Funktion nicht benötigt, dass die Basis teilerfremd zum Modul ist um die Exponenten zu reduzieren). Dadurch spart man sich den CRT. Weiterhin stellt man mit etwas rumprobieren fest, dass A(4,n), A(5,n) und auch A(6,n) extrem schnell stabilisieren (d.h. die Folge der Werte wird konstant), so dass man die sehr großen Werte für n stark vereinfachen kann auf kleine Argumente und daher keine tiefe Rekursion nötig wird.

Tools

Um oft auftauchenden Code leicht wiederverwenden zu können, habe ich einige Teile in extra Dateien ausgelagert.

primetool.rb

Ein primitives Primzahlsieb.

primetool.rb

About

My Project Euler solutions in Ruby

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages