Coding Challenge - Morris Sequence
-
- Strings and string methods are not going to do it. They're too slow and take up too much memory. 2) The only digits you see in any of these numbers are 1, 2, and 3. It seems like a waste to use an entire byte to store each digit. 3) If you graph the math on the progression of the length of these numbers, you'll see that on a LOGARITHMIC SCALE, the graph is about a 40 degree line. What would that look like on a normal X/Y scale? 4) You cannot do this "in memory", without going to the extremes of cleverness, and even then, you'd still need a gargantuan amount of RAM.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak -
Well, he did only ask about the length of the 100 th number. So according to Look-and-say sequence - Wikipedia[^]. Dave told us that the 50th number had length:
L50 = 894810
And the wikipedia article said:
L_n+1/L_n= lambda = 1.303577269034
so....
L50*lambda^(50)= 511175198256
if my math is right enough. Very hard programming challange :D
-
- Strings and string methods are not going to do it. They're too slow and take up too much memory. 2) The only digits you see in any of these numbers are 1, 2, and 3. It seems like a waste to use an entire byte to store each digit. 3) If you graph the math on the progression of the length of these numbers, you'll see that on a LOGARITHMIC SCALE, the graph is about a 40 degree line. What would that look like on a normal X/Y scale? 4) You cannot do this "in memory", without going to the extremes of cleverness, and even then, you'd still need a gargantuan amount of RAM.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave KreskowiakThe length of row n won't exceed twice the length of row n-1 , yes? The result is computable, therefore a Turing Machine can compute it, and, because Turing Machines have virtually unlimited storage, simply use one.
-
The length of row n won't exceed twice the length of row n-1 , yes? The result is computable, therefore a Turing Machine can compute it, and, because Turing Machines have virtually unlimited storage, simply use one.
You build the machine and I'll go make the infinite paper tape.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak -
It's also known as the Conway Sequence, Look and Say Sequence, and probably some others. It's rather simple. Start with a 1 and then describe what you see for the next iteration. So, starting at 1, the next number is one 1 (11), the next is two 1 (21), then one 2 one 1 (1211), and so on:
1
11
21
1211
111221
312211The question to answer is what's the length in digits of the 100th number in the chain, starting with "1" as the first? The first six numbers have been given above. You could write it out by hand, but I wouldn't recommend it, and as developers, that's not what we do. The seemingly simple challenge is to write the code to come up with the answer. The only hint you get is the 50th number is 894,810 digits long. Oh, and don't bother Googling for code. Those examples will only get you so far and definitely won't get you to the answer.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave KreskowiakThe spec isn't clear! Send it back! :wtf: As this is, in essence, a compression algorithm, at line 8->9 (according to the OEIS) I would do:
1113213211
11 132132 11 <== three subsequences
21 2132 21 <== three outputs, eight digits
Which is shorter than their naive result of:
1113213211
111 3 2 1 3 2 11 <== seven subsequences
31 13 12 11 13 12 21 <== seven outputs, fourteen digits
A 40% saving. The complexity of the algorithm increases due to seeking how to split the input into the fewest subsequences of some repetition length (1 in the naive implementation).
-
It's also known as the Conway Sequence, Look and Say Sequence, and probably some others. It's rather simple. Start with a 1 and then describe what you see for the next iteration. So, starting at 1, the next number is one 1 (11), the next is two 1 (21), then one 2 one 1 (1211), and so on:
1
11
21
1211
111221
312211The question to answer is what's the length in digits of the 100th number in the chain, starting with "1" as the first? The first six numbers have been given above. You could write it out by hand, but I wouldn't recommend it, and as developers, that's not what we do. The seemingly simple challenge is to write the code to come up with the answer. The only hint you get is the 50th number is 894,810 digits long. Oh, and don't bother Googling for code. Those examples will only get you so far and definitely won't get you to the answer.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak340472211484 approx (via log extrapolation)
-
The spec isn't clear! Send it back! :wtf: As this is, in essence, a compression algorithm, at line 8->9 (according to the OEIS) I would do:
1113213211
11 132132 11 <== three subsequences
21 2132 21 <== three outputs, eight digits
Which is shorter than their naive result of:
1113213211
111 3 2 1 3 2 11 <== seven subsequences
31 13 12 11 13 12 21 <== seven outputs, fourteen digits
A 40% saving. The complexity of the algorithm increases due to seeking how to split the input into the fewest subsequences of some repetition length (1 in the naive implementation).
When in the :elephant: is the spec Everclear[^] ? Project Euler specs aren't clear either. We always have to do the best we can with what we've got. :-D
1113213211
11 132132 11 <== 13?
21 132132 21 <== three outputs, eight digits
What happened to the 13? The output looks like it should be 10 digits, not 8.
1113213211
111 32132 11
31 32132 21 <== if I understand what you're trying to do
There seems to a problem with representation. How do you tell the difference between single values and a run length value?
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak -
340472211484 approx (via log extrapolation)
Nope, not even close.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak -
When in the :elephant: is the spec Everclear[^] ? Project Euler specs aren't clear either. We always have to do the best we can with what we've got. :-D
1113213211
11 132132 11 <== 13?
21 132132 21 <== three outputs, eight digits
What happened to the 13? The output looks like it should be 10 digits, not 8.
1113213211
111 32132 11
31 32132 21 <== if I understand what you're trying to do
There seems to a problem with representation. How do you tell the difference between single values and a run length value?
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave KreskowiakDave Kreskowiak wrote:
What happened to the 13?
There are 2 132s , hence
2132
.Dave Kreskowiak wrote:
How do you tell the difference between single values and a run length value?
Doesn't matter, but internally (if I write it) it would be in the data structure. It just wouldn't be apparent in the output unless you want it.
(1,1)
(2,1)
...
(2,1),(2,132),(2,1)
...The question is about only the number of digits.
-
340472211484 approx (via log extrapolation)
What base? The length is
10
-- in some base I haven't determined yet. -
It's also known as the Conway Sequence, Look and Say Sequence, and probably some others. It's rather simple. Start with a 1 and then describe what you see for the next iteration. So, starting at 1, the next number is one 1 (11), the next is two 1 (21), then one 2 one 1 (1211), and so on:
1
11
21
1211
111221
312211The question to answer is what's the length in digits of the 100th number in the chain, starting with "1" as the first? The first six numbers have been given above. You could write it out by hand, but I wouldn't recommend it, and as developers, that's not what we do. The seemingly simple challenge is to write the code to come up with the answer. The only hint you get is the 50th number is 894,810 digits long. Oh, and don't bother Googling for code. Those examples will only get you so far and definitely won't get you to the answer.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave KreskowiakSo I stored booleans in a file:
string Morris(int S, int N)
{
string projectPath = System.IO.Path.GetFullPath(@"..\..\..\");
using (BinaryWriter writer = new BinaryWriter(File.Open(projectPath + "input.txt", FileMode.Create)))
{
writer.Write(S > 2);
writer.Write(S == 2);
}for (int i = 1; i < N; i++) { Debug.WriteLine(i+1); using (BinaryReader reader = new BinaryReader(File.Open(projectPath + "input.txt", FileMode.Open))) { int count = 1; bool currMSB = reader.ReadBoolean(); bool currLSB = reader.ReadBoolean(); bool nextMSB, nextLSB; using (BinaryWriter writer = new BinaryWriter(File.Open(projectPath + "output.txt", FileMode.Create))) { while (reader.BaseStream.Position != reader.BaseStream.Length) { nextMSB = reader.ReadBoolean(); nextLSB = reader.ReadBoolean(); if ((currMSB == nextMSB) && (currLSB == nextLSB)) { count++; } else { writer.Write(count > 2); writer.Write(count == 2); writer.Write(currMSB); writer.Write(currLSB); currMSB = nextMSB; currLSB = nextLSB; count = 1; } } writer.Write(count > 2); writer.Write(count == 2); writer.Write(currMSB); writer.Write(currLSB); } } File.Delete(projectPath + "input.txt"); System.IO.File.Copy(projectPath + "output.txt", projectPath + "input.txt"); System.IO.File.WriteAllText(projectPath + "output.txt", string.Empty); } StringBuilder output = new StringBuilder(); using (BinaryReader reader = new BinaryReader(File.Open(projectPath + "input.txt", FileMode.Ope
-
Dave Kreskowiak wrote:
What happened to the 13?
There are 2 132s , hence
2132
.Dave Kreskowiak wrote:
How do you tell the difference between single values and a run length value?
Doesn't matter, but internally (if I write it) it would be in the data structure. It just wouldn't be apparent in the output unless you want it.
(1,1)
(2,1)
...
(2,1),(2,132),(2,1)
...The question is about only the number of digits.
Ah, OK. I missed that. Hmmm. In my implementation, I wrote up a reader/writer that takes care of the "on the fly". This would make an interesting, and challenging, implementation to write. I'll have to look into trying this next weekend. My current implementation writes all the data but there is an option to convert the data to a human-readable format. Not that you'd want to see thousands of pages of 1's, 2's, and 3's, but it did come in handy for analysis when experimenting with implementations.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak -
So I stored booleans in a file:
string Morris(int S, int N)
{
string projectPath = System.IO.Path.GetFullPath(@"..\..\..\");
using (BinaryWriter writer = new BinaryWriter(File.Open(projectPath + "input.txt", FileMode.Create)))
{
writer.Write(S > 2);
writer.Write(S == 2);
}for (int i = 1; i < N; i++) { Debug.WriteLine(i+1); using (BinaryReader reader = new BinaryReader(File.Open(projectPath + "input.txt", FileMode.Open))) { int count = 1; bool currMSB = reader.ReadBoolean(); bool currLSB = reader.ReadBoolean(); bool nextMSB, nextLSB; using (BinaryWriter writer = new BinaryWriter(File.Open(projectPath + "output.txt", FileMode.Create))) { while (reader.BaseStream.Position != reader.BaseStream.Length) { nextMSB = reader.ReadBoolean(); nextLSB = reader.ReadBoolean(); if ((currMSB == nextMSB) && (currLSB == nextLSB)) { count++; } else { writer.Write(count > 2); writer.Write(count == 2); writer.Write(currMSB); writer.Write(currLSB); currMSB = nextMSB; currLSB = nextLSB; count = 1; } } writer.Write(count > 2); writer.Write(count == 2); writer.Write(currMSB); writer.Write(currLSB); } } File.Delete(projectPath + "input.txt"); System.IO.File.Copy(projectPath + "output.txt", projectPath + "input.txt"); System.IO.File.WriteAllText(projectPath + "output.txt", string.Empty); } StringBuilder output = new StringBuilder(); using (BinaryReader reader = new BinaryReader(File.Open(projectPath + "input.txt", FileMode.Ope
Interesting but I question if this is actually writing one byte per value? Don't have time to test right now.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak -
It's also known as the Conway Sequence, Look and Say Sequence, and probably some others. It's rather simple. Start with a 1 and then describe what you see for the next iteration. So, starting at 1, the next number is one 1 (11), the next is two 1 (21), then one 2 one 1 (1211), and so on:
1
11
21
1211
111221
312211The question to answer is what's the length in digits of the 100th number in the chain, starting with "1" as the first? The first six numbers have been given above. You could write it out by hand, but I wouldn't recommend it, and as developers, that's not what we do. The seemingly simple challenge is to write the code to come up with the answer. The only hint you get is the 50th number is 894,810 digits long. Oh, and don't bother Googling for code. Those examples will only get you so far and definitely won't get you to the answer.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave KreskowiakMy instant impression of it is that there has to be a better way than brute force: there's something very Fibonacci-sequence-like about the output... in my head, I can almost predict the pattern from one iteration to the next, without trying to describe anything... if only I had better coffee... if only Dijkstra were still alive... damn it: now you've got me interested.
-
Interesting but I question if this is actually writing one byte per value? Don't have time to test right now.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave KreskowiakI suspect that it is using a byte for each boolean value. As per the usual answers: Why is a boolean 4 bytes in .NET? - Stack Overflow[^] I could store them in a BitVector32 or a BitArray and write that to the file, but I don't have the time to implement it now.
-
I suspect that it is using a byte for each boolean value. As per the usual answers: Why is a boolean 4 bytes in .NET? - Stack Overflow[^] I could store them in a BitVector32 or a BitArray and write that to the file, but I don't have the time to implement it now.
I tried doing this in a BitArray, but found it to be limited in flexibility and performance. This was about 10 years that I originally worked on this problem. I was doing some cleaning around the drive to get rid of old stuff and ran into the project. Then, of course, I just had to run it again and maybe update the code a little bit. :)
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak -
My instant impression of it is that there has to be a better way than brute force: there's something very Fibonacci-sequence-like about the output... in my head, I can almost predict the pattern from one iteration to the next, without trying to describe anything... if only I had better coffee... if only Dijkstra were still alive... damn it: now you've got me interested.
I know there has to be a better way to do it because I did find a list that gave the lengths for the first 3000 numbers in the sequence. Let's just say there are more digits in the 3000th number than there are atoms in the observable universe. I'll post the answer and the length of #3000 Monday morning. It does make for any interesting problem!
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak -
I know there has to be a better way to do it because I did find a list that gave the lengths for the first 3000 numbers in the sequence. Let's just say there are more digits in the 3000th number than there are atoms in the observable universe. I'll post the answer and the length of #3000 Monday morning. It does make for any interesting problem!
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiaklevel 1 size = 1
level 2 size = 2
level 3 size = 2
level 4 size = 4
level 5 size = 6
level 6 size = 6
level 7 size = 8
level 8 size = 10
level 9 size = 14
level 10 size = 20
level 11 size = 26
level 12 size = 34
level 13 size = 46
level 14 size = 62
level 15 size = 78
level 16 size = 102
level 17 size = 134
level 18 size = 176
level 19 size = 226
level 20 size = 302
level 21 size = 408
level 22 size = 528
level 23 size = 678
level 24 size = 904
level 25 size = 1182
level 26 size = 1540
level 27 size = 2012
level 28 size = 2606
level 29 size = 3410
level 30 size = 4462
level 31 size = 5808
level 32 size = 7586
level 33 size = 9898
level 34 size = 12884
level 35 size = 16774
level 36 size = 21890
level 37 size = 28528
level 38 size = 37158
level 39 size = 48410
level 40 size = 63138
level 41 size = 82350
level 42 size = 107312
level 43 size = 139984
level 44 size = 182376
level 45 size = 237746
level 46 size = 310036
level 47 size = 403966
level 48 size = 526646
level 49 size = 686646
level 50 size = 894810
level 51 size = 1166642
level 52 size = 1520986
level 53 size = 1982710
level 54 size = 2584304
level 55 size = 3369156
level 56 size = 4391702
level 57 size = 5724486
level 58 size = 7462860
level 59 size = 9727930
level 60 size = 12680852
level 61 size = 16530884
level 62 size = 21549544
level 63 size = 28091184
level 64 size = 36619162
level 65 size = 47736936
level 66 size = 62226614
level 67 size = 81117366
level 68 size = 105745224
level 69 size = 137842560
level 70 size = 179691598
level 71 size = 234241786
level 72 size = 305351794
level 73 size = 398049970
level 74 size = 518891358
level 75 size = 676414798
level 76 size = 881752750
level 77 size = 1149440192
level 78 size = 1498380104
level 79 size = 1953245418
level 80 size = 2546222700
level 81 size = 3319186080
level 82 size = 4326816254
level 83 size = 5640348764
level 84 size = 7352630884
level 85 size = 9584715106
level 86 size = 12494412020
level 87 size = 16287462624
level 88 size = 21231903676
level 89 size = 27677468012
level 90 size = 36079732206
level 91 size = 47032657188
level 92 size = 61310766500
level 93 size = 79923316046
level 94 size = 104186199146
level 95 size = 135814773100
level 96 size = 177045063068
level 97 size = 230791944956
level 98 size = 300854953626
level 99 size = 392187941864
level 100 size = 511247092564
finished computation at Fri Dec 1 16:48:41 2017
elapsed time: 7205.75secs -
It's also known as the Conway Sequence, Look and Say Sequence, and probably some others. It's rather simple. Start with a 1 and then describe what you see for the next iteration. So, starting at 1, the next number is one 1 (11), the next is two 1 (21), then one 2 one 1 (1211), and so on:
1
11
21
1211
111221
312211The question to answer is what's the length in digits of the 100th number in the chain, starting with "1" as the first? The first six numbers have been given above. You could write it out by hand, but I wouldn't recommend it, and as developers, that's not what we do. The seemingly simple challenge is to write the code to come up with the answer. The only hint you get is the 50th number is 894,810 digits long. Oh, and don't bother Googling for code. Those examples will only get you so far and definitely won't get you to the answer.
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave Kreskowiak:elephant: OK, I'll see how far I get doing it "my way" -- but I'll address the more general problem, allowing the starting input to be more than one symbol and not limited to the symbols
1
,2
, and3
. Also, allowing the caller to specify the maximum subsequence length -- that'll be the hard part. I think the only alcohol in the place is one shot of tequila; it will have to be enough. Sunday morning update: By midnight I had the basic functionality (subsequence lengths 0 and 1) working and tested -- but using a List<T> which means that there are allocation issues. This morning's immediate goal -- implement a SegmentedList<T> class. Sunday afternoon update: The SegmentedList<T> is working well, and it allows for multiple threads for improved speed. -
I tried doing this in a BitArray, but found it to be limited in flexibility and performance. This was about 10 years that I originally worked on this problem. I was doing some cleaning around the drive to get rid of old stuff and ran into the project. Then, of course, I just had to run it again and maybe update the code a little bit. :)
System.ItDidntWorkException: Something didn't work as expected. C# - How to debug code[^]. Seriously, go read these articles.
Dave KreskowiakThey definitely store the booleans as bytes. I ran this:
string MorrisBitVector32(int S, int N)
{
//Need the mask for accessing the individual bits
int[] _masks = new int[32];
{
_masks[0] = BitVector32.CreateMask();
}
for (int i = 1; i < 32; i++)
{
_masks[i] = BitVector32.CreateMask(_masks[i - 1]);
}//Hopefully setes the path to the project folder string projectPath = System.IO.Path.GetFullPath(@"..\\..\\..\\"); using (BinaryWriter writer = new BinaryWriter(File.Open(projectPath + "input.txt", FileMode.Create))) { BitVector32 v = new BitVector32(); // Standard 3 = 11, 2=10,1=01 and // 00 is not more numbers in this BitVector32 v\[\_masks\[0\]\] = S >= 2; v\[\_masks\[1\]\] = S != 2; //Writes a 32bit integer to the file writer.Write(v.Data); } for (int i = 1; i < N; i++) { Debug.WriteLine(i + 1); using (BinaryReader reader = new BinaryReader(File.Open(projectPath + "input.txt", FileMode.Open))) { // Initiates variables for each N run bool currMSB, currLSB, firstRun; firstRun = true; currMSB = false; currLSB = false; int count = 0; int k = 0; BitVector32 outputBits = new BitVector32(); using (BinaryWriter writer = new BinaryWriter(File.Open(projectPath + "output.txt", FileMode.Create))) { while (reader.BaseStream.Position != reader.BaseStream.Length) { BitVector32 inputBits = new BitVector32(reader.ReadInt32()); if (firstRun) { count = 1; currMSB = inputBits\[\_masks\[0\]\]; currLSB = inputBits\[\_masks\[1\]\]; } bool nextMSB, nextLSB; for (int j = (firstRun ? 2 : 0); j < 32; j += 2) { nextMSB = inputBits\[\_ma