Output the smallest powers of 2 with two identical sub-strings of digits n long

5

For each integer n, 0 or higher, output the lowest power of 2 that has two identical sub-strings of n digits in decimal, and the two indices where the digit sub-strings start (0-based).

n      Output      Proof (don't output this)
0 => 0 [0 1]        (_1 & 1_)
1 => 16 [0 4]      (65536 & 65536)
1 => 16 [1 2]      (65536 & 65536)
2 => 24 [0 6]      (16777216 & 16777216)
2 => 24 [2 3]      (16777216 & 16777216)

The possible outputs for the first three inputs are given above. When there is more than one output for a given input, either is acceptable. Only the digit positions will be different. Just output the numbers, the brackets are for clarity only. You don't need to output n.

Output a list of as many as you can find in one minute, or your code runs out of resources, whichever comes first. Please include the output with your answer. If the list is huge, just restrict it to the first and last 5. Your code must be able to find up to n = 9 in under a minute. I've written a Perl program that finds n = 9 after about 20 seconds, so this should be easy to do.

Your code doesn't need to halt itself. It is acceptable if you manually break out if it after a minute.

This is , so lowest number of bytes wins!

CJ Dennis

Posted 2016-02-16T07:17:11.257

Reputation: 4 104

I don't get it, should we output only the lowest power of 2, or as many as we can find in one minute? – Katenkyo – 2016-02-16T08:26:11.630

@CJDennis Should we time it ourself (and halt it) or we can just let it run? – Katenkyo – 2016-02-16T08:33:07.050

3It's not clear if this challenge is a code-golf or [tag:fastest-code]. If you want to keep the primary winning criterion as code-golf, you might want to make a certain speed goal a validity criterion instead (e.g. must return an answer for n = 10 in less than one minute). – primo – 2016-02-16T11:48:57.577

Answers

4

Mathematica, 109 bytes

f@n_:={NestWhile[#+1&,0,Length[p=Position[#,#&@@Commonest@#,1,2]-1]&@Partition[IntegerDigits[2^#],n,1]<2&],p}

n    output
0    {0, {{0},{1}}}
1    {16, {{0},{4}}}
2    {24, {{0},{6}}}
3    {41, {{8},{9}}}
4    {73, {{10},{18}}}
5    {130, {{14},{17}}}
6    {371, {{8},{52}}}
7    {875, {{68},{101}}}
8    {2137, {{12},{240}}}
9    {2900, {{270},{355}}}
10   {7090, {{803},{1123}}}
11   {12840, {{1672},{3185}}}

njpipeorgan

Posted 2016-02-16T07:17:11.257

Reputation: 2 992

I don't know Mathematica very well, so if you can save some bytes by removing some braces in the output, by all means do so. – CJ Dennis – 2016-02-16T08:33:34.817

@CJDennis Actually, that's the natural expression. I didn't add these braces intentionally. – njpipeorgan – 2016-02-16T08:37:49.643

@njpipeorgan isn't your program wrong at least for n=3? I think 2^41=2199023255552, which mean the part found by your program is actually 555 and it overlapse with itself. – Katenkyo – 2016-02-16T09:33:23.580

@Katenkyo 2199023255552 overlaps with 2199023255552 – njpipeorgan – 2016-02-16T09:37:00.053

@njpipeorgan nevermind, just saw overlapping matches are authorized... Which totally invalidate what i was working on. – Katenkyo – 2016-02-16T09:40:25.737

3

Python2, 137 119 bytes

It's pretty straightforward:

i=m=0
while 1:
 n=`2**i`
 for k in range(len(n)-m+1):
    q=n.find(n[k:k+m],k+1)
    if-1<q:print i,k,q;m+=1;break
 else:i+=1

and the output:

n   output
0   0 0 1
1   16 0 4
2   24 0 6
3   41 8 9
4   73 10 18
5   130 14 17
6   371 8 52
7   875 68 101
8   2137 12 240
9   2900 270 355
10  7090 803 1123

18 bytes saved by btwlf

Dica

Posted 2016-02-16T07:17:11.257

Reputation: 409

Welcome, I'm new here too. Trying to find a better solution with if substring in string I figured out some issues which could enhance your bytescore. Firstly str() may be replaced by backticks, see here. Secondly you missed, that p always equals k.

– btwlf – 2016-02-16T23:40:10.660

2

Perl - 99 bytes

use bigint;%_=$_+=$_//1;$%+=($s=$_{$1}//=pos)<pos&&print"$- $s $-[0]
"while/(?=(.{$%}))/g;$-++;do$0

Trading bytes for efficiency. n = 9 finishes in about 25s, around 15x slower than the version below.


Perl - 120 bytes

use bigint;for$i(0..2e4){$_==($s=$_{$_[$_]}//=$_)or($%+=print"$i $s $_
"),last for 0..(@_=/(?=(.{$%}))/g);%_=$_+=$_//=1}

The regex /(?=(.{$%}))/g returns all substrings of the current value of length $%. The list is iterated, and if a value is seen twice, it is reported.


Output

0 0 1
16 1 2
24 2 3
41 8 9
73 10 18
130 14 17
371 8 52
875 68 101
2137 12 240
2900 270 355
7090 803 1123
12840 1672 3185

Output for n = 10 at about 9s, for n = 11 at 30s.

primo

Posted 2016-02-16T07:17:11.257

Reputation: 30 891

If you use -E you can change to say"..." without the linebreak – andlrc – 2016-02-16T17:14:24.903

and -Mbigint is 2 bytes shorter than use bigint; – andlrc – 2016-02-16T17:15:07.753

Cant you change for$i(0..2e4) to while(++$i) if you have no intentions on exiting anyway? – andlrc – 2016-02-16T17:22:33.353

0..2e4 is necessary, or the output is off by one. for(;;$i++) misses the first zero. – primo – 2016-02-16T17:41:38.207