Hofstadter Q sequence: Difference between revisions
Content added Content deleted
(Add Nimrod) |
m ({{out}}) |
||
Line 75: | Line 75: | ||
end Hofstadter_Q_Sequence;</lang> |
end Hofstadter_Q_Sequence;</lang> |
||
{{out}} |
|||
Output: |
|||
<pre> 1 1 2 3 3 4 5 5 6 6 |
<pre> 1 1 2 3 3 4 5 5 6 6 |
||
502 |
502 |
||
Line 109: | Line 109: | ||
printf(($"flips: "g(0)l$, flip)) |
printf(($"flips: "g(0)l$, flip)) |
||
)</lang> |
)</lang> |
||
{{out}} |
|||
<pre> |
<pre> |
||
1 1 2 3 3 4 5 5 6 6 |
1 1 2 3 3 4 5 5 6 6 |
||
Line 137: | Line 138: | ||
return Q |
return Q |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
'''Output:''' |
|||
<pre>First ten: 1, 1, 2, 3, 3, 4, 5, 5, 6, 6, |
<pre>First ten: 1, 1, 2, 3, 3, 4, 5, 5, 6, 6, |
||
1000th: 502 |
1000th: 502 |
||
Line 189: | Line 190: | ||
NEXT |
NEXT |
||
= q%(n%)</lang> |
= q%(n%)</lang> |
||
{{out}} |
|||
'''Output:''' |
|||
<pre> |
<pre> |
||
First 10 terms of Q = 1 1 2 3 3 4 5 5 6 6 |
First 10 terms of Q = 1 1 2 3 3 4 5 5 6 6 |
||
Line 221: | Line 222: | ||
printf("flips: %d\n", flip); |
printf("flips: %d\n", flip); |
||
return 0; |
return 0; |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
<pre>1 1 2 3 3 4 5 5 6 6 |
<pre>1 1 2 3 3 4 5 5 6 6 |
||
502 |
502 |
||
Line 251: | Line 253: | ||
return 0 ; |
return 0 ; |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
Output: |
|||
<pre>The first 10 numbers are: |
<pre>The first 10 numbers are: |
||
1 |
1 |
||
Line 334: | Line 336: | ||
}</lang> |
}</lang> |
||
{{out}} |
|||
'''Output''' |
|||
<pre>Q(1) = 1 |
<pre>Q(1) = 1 |
||
Q(2) = 1 |
Q(2) = 1 |
||
Line 365: | Line 367: | ||
(println "1000th:" (last (qfirst 1000))) |
(println "1000th:" (last (qfirst 1000))) |
||
(println "extra credit:" (->> (qfirst 100000) (partition 2 1) (filter #(apply > %)) count))</lang> |
(println "extra credit:" (->> (qfirst 100000) (partition 2 1) (filter #(apply > %)) count))</lang> |
||
{{out}} |
|||
Output: |
|||
<lang>first 10: [1 1 2 3 3 4 5 5 6 6] |
<lang>first 10: [1 1 2 3 3 4 5 5 6 6] |
||
1000th: 502 |
1000th: 502 |
||
Line 397: | Line 399: | ||
(if (< next-q last-q) (incf c)) |
(if (< next-q last-q) (incf c)) |
||
(setf last-q next-q)) |
(setf last-q next-q)) |
||
finally (return c)))</lang> |
finally (return c)))</lang> |
||
{{out}} |
|||
<pre>First of Q: (1 1 2 3 3 4 5 5 6 6) |
|||
Q(1000): 502 |
Q(1000): 502 |
||
Bumps up to 100000: 49798</ |
Bumps up to 100000: 49798</pre> |
||
Although the above definition of <code>q</code> is more general, for this specific problem the following is faster:<lang lisp>(let ((cc (make-array 3 :element-type 'integer |
Although the above definition of <code>q</code> is more general, for this specific problem the following is faster:<lang lisp>(let ((cc (make-array 3 :element-type 'integer |
||
Line 434: | Line 438: | ||
iota(2, 100_001).count!(i => Q(i) < Q(i - 1))); |
iota(2, 100_001).count!(i => Q(i) < Q(i - 1))); |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
Output: |
|||
<pre>Q(n) for n = [1..10] is: [1, 1, 2, 3, 3, 4, 5, 5, 6, 6] |
<pre>Q(n) for n = [1..10] is: [1, 1, 2, 3, 3, 4, 5, 5, 6, 6] |
||
Q(1000) = 502 |
Q(1000) = 502 |
||
Line 522: | Line 526: | ||
print("value is smaller than previous $count times"); |
print("value is smaller than previous $count times"); |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
Output: |
|||
<pre>Q(1)=1 |
<pre>Q(1)=1 |
||
Q(2)=1 |
Q(2)=1 |
||
Line 587: | Line 591: | ||
Acc = array:set(1, 1, Tmp), |
Acc = array:set(1, 1, Tmp), |
||
hofstadter(?MAX, 2, Acc, 0). |
hofstadter(?MAX, 2, Acc, 0). |
||
</lang> |
</lang> |
||
{{out}} |
|||
<pre> |
<pre> |
||
The first ten terms are: 1, 1, 2, 3, 3, 4, 5, 5, 6, 6 |
The first ten terms are: 1, 1, 2, 3, 3, 4, 5, 5, 6, 6 |
||
Line 613: | Line 618: | ||
printfn "q(1000) = %A" (q 1000I) |
printfn "q(1000) = %A" (q 1000I) |
||
printfn "descents(100000) = %A" (Seq.sum (Seq.init 100000 (fun i -> if q(bigint(i)) > q(bigint(i+1)) then 1 else 0)))</lang> |
printfn "descents(100000) = %A" (Seq.sum (Seq.init 100000 (fun i -> if q(bigint(i)) > q(bigint(i+1)) then 1 else 0)))</lang> |
||
{{out}} |
|||
Output |
|||
<pre>q(1 .. 10) = 1 1 2 3 3 4 5 5 6 6 |
<pre>q(1 .. 10) = 1 1 2 3 3 4 5 5 6 6 |
||
q(1000) = 502 |
q(1000) = 502 |
||
Line 676: | Line 681: | ||
fmt.Printf("Q(%d) = %d\n", n, q(n)) |
fmt.Printf("Q(%d) = %d\n", n, q(n)) |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Q(1) = 1 |
Q(1) = 1 |
||
Line 730: | Line 735: | ||
_S f g x = f x (g x)</lang> |
_S f g x = f x (g x)</lang> |
||
{{out}} |
|||
Output: |
|||
<lang Haskell>Prelude Main> qSeqTest 1000 100000 -- reversals in 100,000 |
<lang Haskell>Prelude Main> qSeqTest 1000 100000 -- reversals in 100,000 |
||
([1,1,2,3,3,4,5,5,6,6],502,49798) |
([1,1,2,3,3,4,5,5,6,6],502,49798) |
||
Line 832: | Line 836: | ||
[http://www.cs.arizona.edu/icon/library/src/procs/printf.icn printf.icn provides formatting] |
[http://www.cs.arizona.edu/icon/library/src/procs/printf.icn printf.icn provides formatting] |
||
{{out}} |
|||
<pre>Q(1 to 10) - verified. |
|||
Q[1000]=502 - verified. |
Q[1000]=502 - verified. |
||
Q(16)=9 < Q(15)=10 |
Q(16)=9 < Q(15)=10 |
||
Line 919: | Line 924: | ||
} |
} |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
Output: |
|||
<pre>Q(1) = 1 |
<pre>Q(1) = 1 |
||
Q(2) = 1 |
Q(2) = 1 |
||
Line 955: | Line 960: | ||
console.log('Q(1000) = ' + hofstadterQ(1000)); |
console.log('Q(1000) = ' + hofstadterQ(1000)); |
||
</lang> |
</lang> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Q(1) = 1 |
Q(1) = 1 |
||
Line 1,039: | Line 1,044: | ||
end</lang> |
end</lang> |
||
{{out}} |
|||
Output: |
|||
<lang julia>julia> Q(1:10) |
<lang julia>julia> Q(1:10) |
||
10-element Array{Int64,1}: |
10-element Array{Int64,1}: |
||
Line 1,110: | Line 1,115: | ||
Hofstadter[n - Hofstadter[n - 1]] + Hofstadter[n - Hofstadter[n - 2]] |
Hofstadter[n - Hofstadter[n - 1]] + Hofstadter[n - Hofstadter[n - 2]] |
||
]</lang> |
]</lang> |
||
{{out}} |
|||
Output: |
|||
<lang Mathematica>Hofstadter /@ Range[10] |
<lang Mathematica>Hofstadter /@ Range[10] |
||
{1,1,2,3,3,4,5,5,6,6} |
{1,1,2,3,3,4,5,5,6,6} |
||
Line 1,156: | Line 1,161: | ||
inc lessCount |
inc lessCount |
||
echo lessCount</lang> |
echo lessCount</lang> |
||
{{out}} |
|||
Output: |
|||
<pre>@[1, 1, 2, 3, 3, 4, 5, 5, 6, 6] |
<pre>@[1, 1, 2, 3, 3, 4, 5, 5, 6, 6] |
||
502 |
502 |
||
Line 1,168: | Line 1,173: | ||
print("1000-th term: "Q[1000],if(Q[1000]==502," (as expected)"," (in error)"));</lang> |
print("1000-th term: "Q[1000],if(Q[1000]==502," (as expected)"," (in error)"));</lang> |
||
{{out}} |
|||
Output: |
|||
<pre>First 10 terms: [1, 1, 2, 3, 3, 4, 5, 5, 6, 6] (as expected) |
<pre>First 10 terms: [1, 1, 2, 3, 3, 4, 5, 5, 6, 6] (as expected) |
||
1000-th term: 502 (as expected)</pre> |
1000-th term: 502 (as expected)</pre> |
||
Line 1,197: | Line 1,202: | ||
writeln('Flips: ', flips); |
writeln('Flips: ', flips); |
||
end.</lang> |
end.</lang> |
||
{{out}} |
|||
Output: |
|||
<pre>:> ./HofstadterQSequence |
<pre>:> ./HofstadterQSequence |
||
1 1 2 3 3 4 5 5 6 6 |
1 1 2 3 3 4 5 5 6 6 |
||
Line 1,227: | Line 1,232: | ||
"than their preceding terms!\n"; |
"than their preceding terms!\n"; |
||
</lang> |
</lang> |
||
{{out}} |
|||
Output: |
|||
<pre>1 |
<pre>1 |
||
1 |
1 |
||
Line 1,242: | Line 1,247: | ||
</pre> |
</pre> |
||
Here's a second solution. |
|||
Here's a second solution. This solution uses tie to make the Q sequence look like a regular array, and only fills the cache on demand. Some pre-allocation is done which provides a minor speed increase for the extra credit. I could have chosen to do recursion instead of iteration, as perl has no limit on how deeply one may recurse, but did not see the benefit of doing so. |
|||
This solution uses tie to make the Q sequence look like a regular array, and only fills the cache on demand. |
|||
Some pre-allocation is done which provides a minor speed increase for the extra credit. |
|||
I could have chosen to do recursion instead of iteration, as perl has no limit on how deeply one may recurse, but did not see the benefit of doing so. |
|||
<lang Perl>#!perl |
<lang Perl>#!perl |
||
Line 1,280: | Line 1,288: | ||
print "Extra credit: $count\n"; |
print "Extra credit: $count\n"; |
||
</lang> |
</lang> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
1 1 2 3 3 4 5 5 6 6 |
1 1 2 3 3 4 5 5 6 6 |
||
Line 1,372: | Line 1,380: | ||
end H; |
end H; |
||
</lang> |
</lang> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
How many values do you want? : |
How many values do you want? : |
||
Line 1,398: | Line 1,406: | ||
n=1000 502 |
n=1000 502 |
||
</pre> |
</pre> |
||
{{out}} for n=100,000 |
|||
<pre> |
<pre> |
||
n=100000 48157 |
n=100000 48157 |
||
Line 1,411: | Line 1,419: | ||
put skip data (tally); |
put skip data (tally); |
||
</lang> |
</lang> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
n=100000 48157 |
n=100000 48157 |
||
Line 1,461: | Line 1,469: | ||
sum(k1 < k0 for k0, k1 in zip(q.seq[1:], q.seq[2:])))</lang> |
sum(k1 < k0 for k0, k1 in zip(q.seq[1:], q.seq[2:])))</lang> |
||
{{out|Combined output}} |
|||
<pre>Q(n) for n = [1..10] is: 1, 1, 2, 3, 3, 4, 5, 5, 6, 6 |
<pre>Q(n) for n = [1..10] is: 1, 1, 2, 3, 3, 4, 5, 5, 6, 6 |
||
Q(1000) = 502 |
Q(1000) = 502 |
||
Q(i+1) < Q(i) for i [1..10000] is true 49798 times.</pre> |
Q(i+1) < Q(i) for i [1..10000] is true 49798 times.</pre> |
||
===Alternative=== |
===Alternative=== |
||
<lang python>def q(n): |
<lang python>def q(n): |
||
Line 1,534: | Line 1,543: | ||
end /*j*/ |
end /*j*/ |
||
return q.x /*return the Xth term to caller.*/</lang> |
return q.x /*return the Xth term to caller.*/</lang> |
||
{{out}} |
|||
'''output''' |
|||
<pre> |
<pre> |
||
1 1 |
1 1 |
||
Line 1,553: | Line 1,562: | ||
===non-recursive, simpler=== |
===non-recursive, simpler=== |
||
This REXX example is identical to the first version |
This REXX example is identical to the first version |
||
except that it uses a function to retrieve array elements with index expressions. |
|||
<lang rexx>/*REXX program to generate Hofstadter Q sequence for any N. */ |
<lang rexx>/*REXX program to generate Hofstadter Q sequence for any N. */ |
||
q.=1 /*negative #s won't have values displayed.*/ |
q.=1 /*negative #s won't have values displayed.*/ |
||
Line 1,577: | Line 1,587: | ||
/*──────────────────────────────────Q subroutine────────────────────────*/ |
/*──────────────────────────────────Q subroutine────────────────────────*/ |
||
q: parse arg ?; return q.? /*return value of Q.? to invoker.*/</lang> |
q: parse arg ?; return q.? /*return value of Q.? to invoker.*/</lang> |
||
'''output''' is identical to the first version. |
'''output''' is identical to the first version.<br> |
||
<br><br> |
|||
===recursive=== |
===recursive=== |
||
Line 1,606: | Line 1,615: | ||
if q.n==0 then q.n=QR(n-QR(n-1)) + QR(n-QR(n-2)) /*¬defined? Define it*/ |
if q.n==0 then q.n=QR(n-QR(n-1)) + QR(n-QR(n-2)) /*¬defined? Define it*/ |
||
return q.n /*return with the value. */</lang> |
return q.n /*return with the value. */</lang> |
||
'''output''' is identical to the first version. |
'''output''' is identical to the first version.<br><br> |
||
The recursive version took over five times longer than the non-recursive version.<br> |
|||
<br><br> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
Line 1,633: | Line 1,641: | ||
end |
end |
||
puts "number of times in the first 100,000 terms where Q(i)<Q(i-1): #{count}"</lang> |
puts "number of times in the first 100,000 terms where Q(i)<Q(i-1): #{count}"</lang> |
||
{{out}} |
|||
output |
|||
<pre>first 10 numbers in the sequence: [1, 1, 2, 3, 3, 4, 5, 5, 6, 6] |
<pre>first 10 numbers in the sequence: [1, 1, 2, 3, 3, 4, 5, 5, 6, 6] |
||
1000'th term: 502 |
1000'th term: 502 |
||
number of times in the first 100,000 terms where Q(i)<Q(i-1): 49798</pre> |
number of times in the first 100,000 terms where Q(i)<Q(i-1): 49798</pre> |
||
=={{header|Run BASIC}}== |
=={{header|Run BASIC}}== |
||
Line 1,650: | Line 1,657: | ||
if i > 20 then print "n=";using("####",i);using("####",Q(i)) |
if i > 20 then print "n=";using("####",i);using("####",Q(i)) |
||
end |
end |
||
</lang |
</lang> |
||
{{out}} |
|||
<pre> |
|||
How many values do you want? :?1000 |
How many values do you want? :?1000 |
||
n= 1 1 |
n= 1 1 |
||
Line 1,677: | Line 1,686: | ||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
{{works with|Scala|2.9.1}} |
{{works with|Scala|2.9.1}} |
||
Naive but elegant version using only recursion doesn't work |
Naive but elegant version using only recursion doesn't work |
||
because runtime is excessive increasing ... |
|||
<lang scala>object HofstadterQseq extends App { |
<lang scala>object HofstadterQseq extends App { |
||
val Q: Int => Int = n => { |
val Q: Int => Int = n => { |
||
Line 1,688: | Line 1,698: | ||
Unfortunately the function Q isn't tail recursiv, |
Unfortunately the function Q isn't tail recursiv, |
||
therefore the compiler can't optimize it. |
|||
Thus we are forced to use a caching featured version. |
|||
<lang scala>object HofstadterQseq extends App { |
<lang scala>object HofstadterQseq extends App { |
||
Line 1,709: | Line 1,721: | ||
println((3 to 100000).filter(i=>Q(i)<Q(i-1)).size) |
println((3 to 100000).filter(i=>Q(i)<Q(i-1)).size) |
||
}</lang> |
}</lang> |
||
{{out}} |
|||
<pre>Q(1) = 1 |
<pre>Q(1) = 1 |
||
Q(2) = 1 |
Q(2) = 1 |
||
Line 1,724: | Line 1,736: | ||
=={{header|Scheme}}== |
=={{header|Scheme}}== |
||
I wish there were a portable way to <code>define-syntax</code>, |
I wish there were a portable way to <code>define-syntax</code>, |
||
or to resize arrays, or to do formated output--anything to make the code |
|||
less silly looking while still run under more than one interpreter. |
|||
<lang lisp>(define qc '#(0 1 1)) |
<lang lisp>(define qc '#(0 1 1)) |
||
(define filled 3) |
(define filled 3) |
||
Line 1,771: | Line 1,785: | ||
(if (>= i 100000) s |
(if (>= i 100000) s |
||
(loop (+ s (if (> (q i) (q (+ 1 i))) 1 0)) (+ 1 i))))) |
(loop (+ s (if (> (q i) (q (+ 1 i))) 1 0)) (+ 1 i))))) |
||
(newline)</lang> |
(newline)</lang> |
||
{{out}} |
|||
<pre>Q(1 .. 10): 1 1 2 3 3 4 5 5 6 6 |
|||
Q(1000): 502 |
Q(1000): 502 |
||
bumps up to 100000: 49798</ |
bumps up to 100000: 49798</pre> |
||
=={{header|Seed7}}== |
=={{header|Seed7}}== |
||
Line 1,815: | Line 1,831: | ||
end func;</lang> |
end func;</lang> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
q(n) for n = 1 .. 10: |
q(n) for n = 1 .. 10: |
||
Line 1,848: | Line 1,864: | ||
} |
} |
||
puts "Q(i)<Q(i-1) for i \[2..100000\] is true $count times"</lang> |
puts "Q(i)<Q(i-1) for i \[2..100000\] is true $count times"</lang> |
||
{{out}} |
|||
Output: |
|||
<pre> |
<pre> |
||
Q(1) == 1 |
Q(1) == 1 |