2009-03-31 16:41first 10 digit prime in consecutive digits of eThere was once a recruitment campaign by Google which involved putting this mysterious message on billboards: { first 10 digit prime in consecutive digits of e } . com which many people solved and it lead them to a website and down a rabbit hole further testing their abilities. I had a go at this question myself and did manage to find the answer, but I didn’t record the method I used. It definitely involved a long command I typed into a terminal window, but I have a feeling I “cheated” by using a semi-colon. What I mean is, my solution wasn’t technically a “one-liner”, and was therefore no more interesting than a solution written in any other language. While emailing a friend of mine recently, this puzzle came to mind, and I decided that I would see if I could write a one-line BASH script to generate the answer. I did manage to, but it’s a little bit scary, so I’ll share it with you and try to explain it in this blog post. The One-Linerecho -e "scale=1000 \\0073 e(1)" | bc -l | tr -d [\\\\\\n] | cut -c 3- | sed 's/\(..........\)\(..........\)/\1\n\1\2\n\2/g' | sed 's/\(....................\)/A\1\nB\1\nC\1\nD\1\nE\1\nF\1\nG\1\nH\1\nI\1\nJ\1/' | sed 's/A//' | sed 's/B.//' | sed 's/C..//' | sed 's/D...//' | sed 's/E....//' | sed 's/F.....//' | sed 's/G......//' | sed 's/H.......//' | sed 's/I........//' | sed 's/J.........//' | sed 's/^\(..........\).*/\1/' | factor | grep -v ": [0-9]* " | head -1 | sed 's/:.*//'
or, without highlighting:
And so it beginsAlthough technically it is still a one-liner if you use semi-colons inside strings, I wanted to be extra strict and avoid the use of them altogether. This is significant in the arguments to the initial This string, then, is piped into 2.718281828459045235360287471352662497757247093699959574966967627724\ 07663035354759457138217852516642742746639193200305992181741359662904\ 35729003342952605956307381323286279434907632338298807531952510190115\ 73834187930702154089149934884167509244761460668082264800168477411853\ 74234544243710753907774499206955170276183860626133138458300075204493\ 38265602976067371132007093287091274437470472306969772093101416928368\ 19025515108657463772111252389784425056953696770785449969967946864454\ 90598793163688923009879312773617821542499922957635148220826989519366\ 80331825288693984964651058209392398294887933203625094431173012381970\ 68416140397019837679320683282376464804295311802328782509819455815301\ 75671736133206981125099618188159304169035159888851934580727386673858\ 94228792284998920868058257492796104841984443634632449684875602336248\ 27041978623209002160990235304369941849146314093431738143640546253152\ 09618369088870701676839642437814059271456354906130310720851038375051\ 01157477041718986106873969655212671546889570350354 From this it is clear that The output is then one long line, but for cleanliness, I wanted to remove everything before the decimal point (or decimal comma), inclusive. As DecompositionTrust me for now that the input into 6965521267: 5987 1163441 whereas for a prime number like 7: 7 The difference between the output for prime numbers and for composite numbers, then, is that prime numbers don’t produce output which has “a colon then a space then a (perhaps multi-digit) number then a space”. There is no need for a space after the first factor of a prime number, because that first factor is the only factor (apart from The puzzle asks for the “first” prime number found, so the output stream can stop after the first line found by The difficult bitSo, the input of a long string of decimal digits of The step of creating duplicate information was itself a two step process, but both used a clever trick with To begin the duplication, then, the input string of digits is considered in blocks of 20, with the first 10 being captured as one sub-expression and the other 10 being captured as a second, and these sub-expressions are used like building blocks to build an even bigger block. For clarity, I will assign the first sub-expression to the letter #A AB B# where the hashes are gaps to filled by the next match. Since the Carrying on the duplication process, the next step is to create 10 copies of each of these lines, but each clone must be identifiable, so a letter prefix is used (ignoring the fact that I used letters to explain the previous step). When replacing a matched regular expression, The type of trimming that needs to be done is different for each of the 10 rows that were created in the last step, but as these lines each have a unique prefix, this means there are just 10 rules needed, each one specific to a single prefix. So the Here is what a block of 10 duplicate lines look like before these A71828182845904523536 B71828182845904523536 C71828182845904523536 D71828182845904523536 E71828182845904523536 F71828182845904523536 G71828182845904523536 H71828182845904523536 I71828182845904523536 J71828182845904523536 and after: 71828182845904523536 1828182845904523536 828182845904523536 28182845904523536 8182845904523536 182845904523536 82845904523536 2845904523536 845904523536 45904523536 The indiscriminate ConclusionYou may have noticed that the script contains one hard-coded number, the number Taking a more mathematical approach, one could consider that the distribution of primes tends towards The only remaining question is, since I excluded the initial Comments
Display comments as
(Linear | Threaded)
Two alternatives come to mind, if you don't mind doing something bad:
echo -e "scale=1000 \\0073 e(1)" | bc -l | tr -d [\\\\\\n] | cut -c 3- |sed 's/.*/printf "\0\n"x1000/' |perl |nl |sed 's/^[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*$/echo "\2" | cut -c \1-$((\1+9))/'|bash|grep -v "^0"|factor|grep "^[0-9]*: [0-9]*$"|head -1|sed 's/:.*//'
Borrows your boilerplate and replaces the interesting bit with a slight infraction of your rules (but the purity in a functional-programming sense (which is surely why one-liners are good) is still there).
As to the second, I should probably be beaten for suggesting this, but anyways:
seq 11 1000 |sed 's/.*/scale=\0; e(1);/'|bc -l|tr "\n" "a"|sed 's/\\a//g'|tr "a" "\n"|sed 's/^.*\([0-9]\{10\}\)/\1/'|grep -v "^0" |factor |grep "^[0-9]\{10\}: [0-9]*$"|head -1|sed 's/:.*//' echo $e| { grep "^[0-9]\{10-\}" | sed 's/^[0-9]\([0-9]\{9\}\)\(.*\)$/\2\3 \1\2/' | tee /dev/fd/0; }
But I don't see how to actually make this loop like I want (acrobatics with the `read' command and even with named pipes have proven fruitless thus far), nor how I'd get out of it if I did manage to get it to work (this is sort of what the initial grep is meant for). But this flavor of thing would generalize nicely.
(Also, the hint below the comment box about using geshi in comments should have closing tag for geshi, rather than for a (fictitious?) `lang' tag.)
|
QuicksearchCategoriesSyndicate This BlogBlog Administration |
A friend of mine was apparently inspired by my solution to the problem of finding the first 10 digit prime number in the digits of e, and he told me about a seemingly similar problem he faced while trying to manipulate a text file he had created in a custom format.
Tracked: Apr 28, 22:40