This commit is contained in:
Ingy döt Net 2013-04-10 21:29:02 -07:00
parent 764da6cbbb
commit db842d013d
19005 changed files with 197040 additions and 7 deletions

View file

@ -0,0 +1,14 @@
The [[wp:Hofstadter_sequence#Hofstadter_Q_sequence|Hofstadter Q sequence]] is defined as:
:<math>\begin{align}
Q(1)&=Q(2)=1, \\
Q(n)&=Q\big(n-Q(n-1)\big)+Q\big(n-Q(n-2)\big), \quad n>2.
\end{align}</math>
It is defined like the [[Fibonacci sequence]], but whereas the next term in the Fibonacci sequence is the sum of the previous two terms, in the Q sequence the previous two terms tell you how far to go back in the Q sequence to find the two numbers to sum to make the next term of the sequence.
;Task:
* Confirm and display that the first ten terms of the sequence are: 1, 1, 2, 3, 3, 4, 5, 5, 6, and 6
* Confirm and display that the 1000<sup>th</sup> term is: 502
;Optional extra credit
* Count and display how many times a member of the sequence is less than its preceding term for terms up to and including the 100,000'th term.
* Ensure that the extra credit solution 'safely' handles being initially asked for an n'th term where n is large.<br> (This point is to ensure that caching and/or recursion limits, if it is a concern, is correctly handled).

View file

@ -0,0 +1,24 @@
#!/usr/local/bin/a68g --script #
INT n = 100000;
main:
(
INT flip;
[n]INT q;
q[1] := q[2] := 1;
FOR i FROM 3 TO n DO
q[i] := q[i - q[i - 1]] + q[i - q[i - 2]] OD;
FOR i TO 10 DO
printf(($g(0)$, q[i], $b(l,x)$, i = 10)) OD;
printf(($g(0)l$, q[1000]));
flip := 0;
FOR i TO n-1 DO
flip +:= ABS (q[i] > q[i + 1]) OD;
printf(($"flips: "g(0)l$, flip))
)

View file

@ -0,0 +1,22 @@
#!/usr/bin/awk -f
BEGIN {
N = 100000;
print "Q-sequence(1..10) : " Qsequence(10);
Qsequence(N,Q);
print "1000th number of Q sequence : " Q[1000];
for (n=2; n<=N; n++) {
if (Q[n]<Q[n-1]) NN++;
}
print "number of Q(n)<Q(n+1) for n<=100000 : " NN;
}
function Qsequence(N,Q) {
Q[1] = 1;
Q[2] = 1;
seq = "1 1";
for (n=3; n<=N; n++) {
Q[n] = Q[n-Q[n-1]]+Q[n-Q[n-2]];
seq = seq" "Q[n];
}
return seq;
}

View file

@ -0,0 +1,59 @@
with Ada.Text_IO;
procedure Hofstadter_Q_Sequence is
type Callback is access procedure(N: Positive);
procedure Q(First, Last: Positive; Q_Proc: Callback) is
-- calls Q_Proc(Q(First)); Q_Proc(Q(First+1)); ... Q_Proc(Q(Last));
-- precondition: Last > 2
Q_Store: array(1 .. Last) of Natural := (1 => 1, 2 => 1, others => 0);
-- "global" array to store the Q(I)
-- if Q_Store(I)=0, we compute Q(I) and update Q_Store(I)
-- else we already know Q(I) = Q_Store(I)
function Q(N: Positive) return Positive is
begin
if Q_Store(N) = 0 then
Q_Store(N) := Q(N - Q(N-1)) + Q(N-Q(N-2));
end if;
return Q_Store(N);
end Q;
begin
for I in First .. Last loop
Q_Proc(Q(I));
end loop;
end Q;
procedure Print(P: Positive) is
begin
Ada.Text_IO.Put(Positive'Image(P));
end Print;
Decrease_Counter: Natural := 0;
Previous_Value: Positive := 1;
procedure Decrease_Count(P: Positive) is
begin
if P < Previous_Value then
Decrease_Counter := Decrease_Counter + 1;
end if;
Previous_Value := P;
end Decrease_Count;
begin
Q(1, 10, Print'Access);
-- the first ten terms of the sequence are: 1, 1, 2, 3, 3, 4, 5, 5, 6, and 6
Ada.Text_IO.New_Line;
Q(1000, 1000, Print'Access);
-- the 1000'th term is: 502
Ada.Text_IO.New_Line;
Q(2, 100_000, Decrease_Count'Access);
Ada.Text_IO.Put_Line(Integer'Image(Decrease_Counter));
-- how many times a member of the sequence is less than its preceding term
-- for terms up to and including the 100,000'th term
end Hofstadter_Q_Sequence;

View file

@ -0,0 +1,18 @@
PRINT "First 10 terms of Q = " ;
FOR i% = 1 TO 10 : PRINT ;FNq(i%, c%) " "; : NEXT : PRINT
PRINT "1000th term = " ; FNq(1000, c%)
PRINT "100000th term = " ; FNq(100000, c%)
PRINT "Term is less than preceding term " ; c% " times"
END
DEF FNq(n%, RETURN c%)
LOCAL i%,q%()
IF n% < 3 THEN = 1 ELSE IF n% = 3 THEN = 2
DIM q%(n%)
q%(1) = 1 : q%(2) = 1 : q%(3) = 2
c% = 0
FOR i% = 3 TO n%
q%(i%) = q%(i% - q%(i%-1)) + q%(i% - q%(i%-2))
IF q%(i%) < q%(i%-1) THEN c% += 1
NEXT
= q%(n%)

View file

@ -0,0 +1,21 @@
#include <iostream>
int main( ) {
int hofstadters[100000] ;
hofstadters[ 0 ] = 1 ;
hofstadters[ 1 ] = 1 ;
for ( int i = 3 ; i < 100000 ; i++ )
hofstadters[ i - 1 ] = hofstadters[ i - 1 - hofstadters[ i - 1 - 1 ]] +
hofstadters[ i - 1 - hofstadters[ i - 2 - 1 ]] ;
std::cout << "The first 10 numbers are:\n" ;
for ( int i = 0 ; i < 10 ; i++ )
std::cout << hofstadters[ i ] << std::endl ;
std::cout << "The 1000'th term is " << hofstadters[ 999 ] << " !" << std::endl ;
int less_than_preceding = 0 ;
for ( int i = 0 ; i < 99999 ; i++ ) {
if ( hofstadters[ i + 1 ] < hofstadters[ i ] )
less_than_preceding++ ;
}
std::cout << less_than_preceding << " times a number was preceded by a greater number!\n" ;
return 0 ;
}

View file

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
namespace HofstadterQSequence
{
class Program
{
// Initialize the dictionary with the first two indices filled.
private static readonly Dictionary<int, int> QList = new Dictionary<int, int>
{
{1, 1},
{2, 1}
};
private static void Main()
{
int lessThanLast = 0;
/* Initialize our variable that holds the number of times
* a member of the sequence was less than its preceding term. */
for (int n = 1; n <= 100000; n++)
{
int q = Q(n); // Get Q(n).
if (n > 1 && QList[n - 1] > q) // If Q(n) is less than Q(n - 1),
lessThanLast++; // then add to the counter.
if (n > 10 && n != 1000) continue; /* If n is greater than 10 and not 1000,
* the rest of the code in the loop does not apply,
* and it will be skipped. */
if (!Confirm(n, q)) // Confirm Q(n) is correct.
throw new Exception(string.Format("Invalid result: Q({0}) != {1}", n, q));
Console.WriteLine("Q({0}) = {1}", n, q); // Write Q(n) to the console.
}
Console.WriteLine("Number of times a member of the sequence was less than its preceding term: {0}.",
lessThanLast);
}
private static bool Confirm(int n, int value)
{
if (n <= 10)
return new[] {1, 1, 2, 3, 3, 4, 5, 5, 6, 6}[n - 1] == value;
if (n == 1000)
return 502 == value;
throw new ArgumentException("Invalid index.", "n");
}
private static int Q(int n)
{
int q;
if (!QList.TryGetValue(n, out q)) // Try to get Q(n) from the dictionary.
{
q = Q(n - Q(n - 1)) + Q(n - Q(n - 2)); // If it's not available, then calculate it.
QList.Add(n, q); // Add it to the dictionary.
}
return q;
}
}
}

View file

@ -0,0 +1,24 @@
#include <stdio.h>
#include <stdlib.h>
#define N 100000
int main()
{
int i, flip, *q = (int*)malloc(sizeof(int) * N) - 1;
q[1] = q[2] = 1;
for (i = 3; i <= N; i++)
q[i] = q[i - q[i - 1]] + q[i - q[i - 2]];
for (i = 1; i <= 10; i++)
printf("%d%c", q[i], i == 10 ? '\n' : ' ');
printf("%d\n", q[1000]);
for (flip = 0, i = 1; i < N; i++)
flip += q[i] > q[i + 1];
printf("flips: %d\n", flip);
return 0;
}

View file

@ -0,0 +1,27 @@
(defparameter *mm* (make-hash-table :test #'equal))
;;; generic memoization macro
(defmacro defun-memoize (f (&rest args) &body body)
(defmacro hash () `(gethash (cons ',f (list ,@args)) *mm*))
(let ((h (gensym)))
`(defun ,f (,@args)
(let ((,h (hash)))
(if ,h ,h
(setf (hash) (progn ,@body)))))))
;;; def q
(defun-memoize q (n)
(if (<= n 2) 1
(+ (q (- n (q (- n 1))))
(q (- n (q (- n 2)))))))
;;; test
(format t "First of Q: ~a~%Q(1000): ~a~%Bumps up to 100000: ~a~%"
(loop for i from 1 to 10 collect (q i))
(q 1000)
(loop with c = 0 with last-q = (q 1)
for i from 2 to 100000
do (let ((next-q (q i)))
(if (< next-q last-q) (incf c))
(setf last-q next-q))
finally (return c)))

View file

@ -0,0 +1,3 @@
First of Q: (1 1 2 3 3 4 5 5 6 6)
Q(1000): 502
Bumps up to 100000: 49798

View file

@ -0,0 +1,12 @@
(let ((cc (make-array 3 :element-type 'integer
:initial-element 1
:adjustable t
:fill-pointer 3)))
(defun q (n)
(when (>= n (length cc))
(loop for i from (length cc) below n do (q i))
(vector-push-extend
(+ (aref cc (- n (aref cc (- n 1))))
(aref cc (- n (aref cc (- n 2)))))
cc))
(aref cc n)))

View file

@ -0,0 +1,17 @@
import std.stdio, std.algorithm, std.functional, std.range;
int Q(int n) {
assert(n > 0);
alias memoize!Q mQ;
if (n == 1 || n == 2)
return 1;
else
return mQ(n - mQ(n - 1)) + mQ(n - mQ(n - 2));
}
void main() {
writeln("Q(n) for n = [1..10] is: ", map!Q(iota(1, 11)));
writeln("Q(1000) = ", Q(1000));
writefln("Q(i) is less than Q(i-1) for i [2..100_000] %d times.",
count!(i => Q(i) < Q(i-1))(iota(2, 100_001)));
}

View file

@ -0,0 +1,23 @@
import std.stdio, std.algorithm, std.range, std.array;
struct Q {
static Appender!(uint[]) s;
/*nothrow*/ static this() {
s ~= [0, 1, 1];
}
static uint opCall(in int n) /*nothrow*/ {
assert(n > 0);
foreach (immutable i; s.data.length .. n + 1)
s ~= s.data[i - s.data[i - 1]] + s.data[i - s.data[i - 2]];
return s.data[n];
}
}
void main() {
writeln("Q(n) for n = [1..10] is: ", map!Q(iota(1, 11)));
writeln("Q(1000) = ", Q(1000));
writefln("Q(i) is less than Q(i-1) for i [2..100_000] %d times.",
count!(i => Q(i) < Q(i-1))(iota(2, 100_001)));
}

View file

@ -0,0 +1,8 @@
int Q(int n) => n>2 ? Q(n-Q(n-1))+Q(n-Q(n-2)) : 1;
main() {
for(int i=1;i<=10;i++) {
print("Q($i)=${Q(i)}");
}
print("Q(1000)=${Q(1000)}");
}

View file

@ -0,0 +1,42 @@
class Q {
Map<int,int> _table;
Q() {
_table=new Map<int,int>();
_table[1]=1;
_table[2]=1;
}
int q(int n) {
// if the cache is not filled until n-1, fill it starting with the lowest entries first
// this avoids doing a recursion from n to 2 (e.g. if you call q(1000000) first)
// this doesn't happen in the tasks calls since the cache is filled ascending
if(_table[n-1]==null) {
for(int i=_table.length;i<n;i++) {
q(i);
}
}
if(_table[n]==null) {
_table[n]=q(n-q(n-1))+q(n-q(n-2));
}
return _table[n];
}
}
main() {
Q q=new Q();
for(int i=1;i<=10;i++) {
print("Q($i)=${q.q(i)}");
}
print("Q(1000)=${q.q(1000)}");
int count=0;
for(int i=2;i<=100000;i++) {
if(q.q(i)<q.q(i-1)) {
count++;
}
}
print("value is smaller than previous $count times");
}

View file

@ -0,0 +1,17 @@
main() {
List<int> q=new List<int>(100001);
q[1]=q[2]=1;
int count=0;
for(int i=3;i<q.length;i++) {
q[i]=q[i-q[i-1]]+q[i-q[i-2]];
if(q[i]<q[i-1]) {
count++;
}
}
for(int i=1;i<=10;i++) {
print("Q($i)=${q[i]}");
}
print("Q(1000)=${q[1000]}");
print("value is smaller than previous $count times");
}

View file

@ -0,0 +1,30 @@
%% @author Jan Willem Luiten <jwl@secondmove.com>
%% Hofstadter Q Sequence for Rosetta Code
-module(hofstadter).
-export([main/0]).
-define(MAX, 100000).
flip(V2, V1) when V1 > V2 -> 1;
flip(_V2, _V1) -> 0.
list_terms(N, N, Acc) ->
io:format("~w~n", [array:get(N, Acc)]);
list_terms(Max, N, Acc) ->
io:format("~w, ", [array:get(N, Acc)]),
list_terms(Max, N+1, Acc).
hofstadter(N, N, Acc, Flips) ->
io:format("The first ten terms are: "),
list_terms(9, 0, Acc),
io:format("The 1000'th term is ~w~n", [array:get(999, Acc)]),
io:format("Number of flips: ~w~n", [Flips]);
hofstadter(Max, N, Acc, Flips) ->
Qn1 = array:get(N-1, Acc),
Qn = array:get(N - Qn1, Acc) + array:get(N - array:get(N-2, Acc), Acc),
hofstadter(Max, N+1, array:set(N, Qn, Acc), Flips + flip(Qn, Qn1)).
main() ->
Tmp = array:set(0, 1, array:new(?MAX)),
Acc = array:set(1, 1, Tmp),
hofstadter(?MAX, 2, Acc, 0).

View file

@ -0,0 +1,7 @@
( scratchpad ) : next ( seq -- newseq )
dup 2 tail* over length [ swap - ] curry map
[ dupd swap nth ] map 0 [ + ] reduce suffix ;
( scratchpad ) { 1 1 } 1000 [ next ] times dup 10 head . 999 swap nth .
{ 1 1 2 3 3 4 5 5 6 6 }
502

View file

@ -0,0 +1,46 @@
package main
import "fmt"
var m map[int]int
func initMap() {
m = make(map[int]int)
m[1] = 1
m[2] = 1
}
func q(n int) (r int) {
if r = m[n]; r == 0 {
r = q(n-q(n-1)) + q(n-q(n-2))
m[n] = r
}
return
}
func main() {
initMap()
// task
for n := 1; n <= 10; n++ {
showQ(n)
}
// task
showQ(1000)
// extra credit
count, p := 0, 1
for n := 2; n <= 1e5; n++ {
qn := q(n)
if qn < p {
count++
}
p = qn
}
fmt.Println("count:", count)
// extra credit
initMap()
showQ(1e6)
}
func showQ(n int) {
fmt.Printf("Q(%d) = %d\n", n, q(n))
}

View file

@ -0,0 +1,8 @@
qSequence = tail qq where
qq = 0 : 1 : 1 : map g [3..]
g n = qq !! (n - qq !! (n-1)) + qq !! (n - qq !! (n-2))
-- Output:
*Main> (take 10 qSequence, qSequence !! (1000-1))
([1,1,2,3,3,4,5,5,6,6],502)
(0.00 secs, 525044 bytes)

View file

@ -0,0 +1,21 @@
import Data.Array
qSequence n = arr
where
arr = listArray (1,n) $ 1:1: map g [3..n]
g i = arr!(i - arr!(i-1)) +
arr!(i - arr!(i-2))
gradualth m k arr -- gradually precalculate m-th item
| m <= v = pre `seq` arr!m -- in steps of k
where -- to prevent STACK OVERFLOW
pre = foldl1 (\a b-> a `seq` arr!b) [u,u+k..m]
(u,v) = bounds arr
qSeqTest m n = let arr = qSequence $ max m n in
( take 10 . elems $ arr -- 10 first items
, gradualth m 10000 $ arr -- m-th item
, length . filter (> 0) -- reversals in n items
. _S (zipWith (-)) tail . take n . elems $ arr )
_S f g x = f x (g x)

View file

@ -0,0 +1,7 @@
Prelude Main> qSeqTest 1000 100000 -- reversals in 100,000
([1,1,2,3,3,4,5,5,6,6],502,49798)
(0.09 secs, 18879708 bytes)
Prelude Main> qSeqTest 1000000 100000 -- 1,000,000-th item
([1,1,2,3,3,4,5,5,6,6],512066,49798)
(2.80 secs, 87559640 bytes)

View file

@ -0,0 +1,18 @@
import Data.Array
q = qq (listArray (1,2) [1,1]) 1 where
qq ar n = (arr!n) : qq arr (n+1) where
l = snd (bounds ar)
step n =arr!(n - (fromIntegral (arr!(n - 1)))) +
arr!(n - (fromIntegral (arr!(n - 2))))
arr :: Array Int Integer
arr | n <= l = ar
| otherwise = listArray (1, l*2)$
([ar!i | i <- [1..l]] ++
[step i | i <- [l+1..l*2]])
main = do
putStr("first 10: "); print (take 10 q)
putStr("1000-th: "); print (q !! 999)
putStr("flips: ")
print $ length $ filter id $ take 100000 (zipWith (>) q (tail q))

View file

@ -0,0 +1,20 @@
import Data.Array
import Data.Int (Int64)
q = qq [listArray (1,2) [1,1]] 1 where
qq a n = seek aa n : qq aa (1 + n) where
aa | n <= l = a
| otherwise = listArray (l+1,l*2) (take l $ drop 2 lst):a
where
l = snd (bounds $ head a)
lst = seek a (l-1):seek a l:(ext lst (l+1))
ext (q1:q2:qs) i = (g (i-q2) + g (i-q1)):ext (q2:qs) (1+i)
g = seek aa
seek (ar:ars) n
| n >= fst (bounds ar) = ar ! n
| otherwise = seek ars n
-- Only a perf test. Task can be done exactly the same as above
main = print $ sum qqq
where qqq :: [Int64]
qqq = map fromIntegral $ take 3000000 q

View file

@ -0,0 +1,39 @@
link printf
procedure main()
V := [1, 1, 2, 3, 3, 4, 5, 5, 6, 6]
every i := 1 to *V do
if Q(i) ~= V[i] then stop("Assertion failure for position ",i)
printf("Q(1 to %d) - verified.\n",*V)
q := Q(n := 1000)
v := 502
printf("Q[%d]=%d - %s.\n",n,v,if q = v then "verified" else "failed")
invcount := 0
every i := 2 to (n := 100000) do
if Q(i) < Q(i-1) then {
printf("Q(%d)=%d < Q(%d)=%d\n",i,Q(i),i-1,Q(i-1))
invcount +:= 1
}
printf("There were %d inversions in Q up to %d\n",invcount,n)
end
procedure Q(n) #: Hofstader Q sequence
static S
initial S := [1,1]
if q := S[n] then return q
else {
q := Q(n - Q(n - 1)) + Q(n - Q(n - 2))
if *S = n - 1 then {
put(S,q)
return q
}
else
runerr(500,n)
}
end

View file

@ -0,0 +1,8 @@
Qs=:0 1 1
Q=: verb define
n=. >./,y
while. n>:#Qs do.
Qs=: Qs,+/(-_2{.Qs){Qs
end.
y{Qs
)

View file

@ -0,0 +1,6 @@
Q 1+i.10
1 1 2 3 3 4 5 5 6 6
Q 1000
502
+/2>/\ Q 1+i.100000
49798

View file

@ -0,0 +1,46 @@
import java.util.HashMap;
import java.util.Map;
public class HofQ {
private static Map<Integer, Integer> q = new HashMap<Integer, Integer>(){{
put(1, 1);
put(2, 1);
}};
private static int[] nUses = new int[100001];//not part of the task
public static int Q(int n){
nUses[n]++;//not part of the task
if(q.containsKey(n)){
return q.get(n);
}
int ans = Q(n - Q(n - 1)) + Q(n - Q(n - 2));
q.put(n, ans);
return ans;
}
public static void main(String[] args){
for(int i = 1; i <= 10; i++){
System.out.println("Q(" + i + ") = " + Q(i));
}
int last = 6;//value for Q(10)
int count = 0;
for(int i = 11; i <= 100000; i++){
int curr = Q(i);
if(curr < last) count++;
last = curr;
if(i == 1000) System.out.println("Q(1000) = " + curr);
}
System.out.println("Q(i) is less than Q(i-1) for i <= 100000 " + count + " times");
//Optional stuff below here
int maxUses = 0, maxN = 0;
for(int i = 1; i<nUses.length;i++){
if(nUses[i] > maxUses){
maxUses = nUses[i];
maxN = i;
}
}
System.out.println("Q(" + maxN + ") was called the most with " + maxUses + " calls");
}
}

View file

@ -0,0 +1,18 @@
var hofstadterQ = function() {
var memo = [1,1,1];
var Q = function (n) {
var result = memo[n];
if (typeof result !== 'number') {
result = Q(n - Q(n-1)) + Q(n - Q(n-2));
memo[n] = result;
}
return result;
};
return Q;
}();
for (var i = 1; i <=10; i += 1) {
console.log('Q('+ i +') = ' + hofstadterQ(i));
}
console.log('Q(1000) = ' + hofstadterQ(1000));

View file

@ -0,0 +1,7 @@
function Q = Qsequence(N)
%% zeros are used to pre-allocate memory, this is not strictly necessary but can significantly improve performance for large N
Q = [1,1,zeros(1,N-2)];
for n=3:N
Q(n) = Q(n-Q(n-1))+Q(n-Q(n-2));
end;
end;

View file

@ -0,0 +1,8 @@
Q := proc( n )
option remember, system;
if n = 1 or n = 2 then
1
else
thisproc( n - thisproc( n - 1 ) ) + thisproc( n - thisproc( n - 2 ) )
end if
end proc:

View file

@ -0,0 +1,5 @@
> seq( Q( i ), i = 1 .. 10 );
1, 1, 2, 3, 3, 4, 5, 5, 6, 6
> Q( 1000 );
502

View file

@ -0,0 +1,8 @@
> flips := 0:
> for i from 2 to 100000 do
> if L[ i ] < L[ i - 1 ] then
> flips := 1 + flips
> end if
> end do:
> flips;
49798

View file

@ -0,0 +1,15 @@
Qflips := proc( n )
local a := Array( 1 .. n );
a[ 1 ] := 1;
a[ 2 ] := 1;
for local i from 3 to n do
a[ i ] := a[ i - a[ i - 1 ] ] + a[ i - a[ i - 2 ] ]
end do;
local flips := 0;
for i from 2 to n do
if a[ i ] < a[ i - 1 ] then
flips := 1 + flips
end if
end do;
flips
end proc:

View file

@ -0,0 +1,2 @@
> Qflips( 10^5 );
49798

View file

@ -0,0 +1,4 @@
Hofstadter[1] = Hofstadter[2] = 1;
Hofstadter[n_Integer?Positive] := Hofstadter[n] = Block[{$RecursionLimit = Infinity},
Hofstadter[n - Hofstadter[n - 1]] + Hofstadter[n - Hofstadter[n - 2]]
]

View file

@ -0,0 +1,6 @@
Hofstadter /@ Range[10]
{1,1,2,3,3,4,5,5,6,6}
Hofstadter[1000]
502
Count[Differences[Hofstadter /@ Range[100000]], _?Negative]
49798

View file

@ -0,0 +1,21 @@
#!/usr/bin/perl
use warnings;
use strict;
my @hofstadters = ( 1 , 1 );
while ( @hofstadters < 100000 ) {
my $nextn = @hofstadters + 1;
# array index counting starts at 0 , so we have to subtract 1 from the numbers!
push @hofstadters , $hofstadters [ $nextn - 1 - $hofstadters[ $nextn - 1 - 1 ] ]
+ $hofstadters[ $nextn - 1 - $hofstadters[ $nextn - 2 - 1 ]];
}
for my $i ( 0..9 ) {
print "$hofstadters[ $i ]\n";
}
print "The 1000'th term is $hofstadters[ 999 ]!\n";
my $less_than_preceding = 0;
for my $i ( 0..99998 ) {
$less_than_preceding++ if $hofstadters[ $i + 1 ] < $hofstadters[ $i ];
}
print "Up to and including the 100000'th term, $less_than_preceding terms are less " .
"than their preceding terms!\n";

View file

@ -0,0 +1,7 @@
(de q (N)
(cache '(NIL) (pack (char (hash N)) N)
(if (>= 2 N)
1
(+
(q (- N (q (dec N))))
(q (- N (q (- N 2)))) ) ) ) )

View file

@ -0,0 +1,9 @@
: (mapcar q (range 1 10))
-> (1 1 2 3 3 4 5 5 6 6)
: (q 1000)
-> 502
: (let L (mapcar q (range 1 100000))
(cnt < (cdr L) L) )
-> 49798

View file

@ -0,0 +1,16 @@
def q(n):
if n < 1 or type(n) != int: raise ValueError("n must be an int >= 1")
try:
return q.seq[n]
except IndexError:
ans = q(n - q(n - 1)) + q(n - q(n - 2))
q.seq.append(ans)
return ans
q.seq = [None, 1, 1]
if __name__ == '__main__':
first10 = [q(i) for i in range(1,11)]
assert first10 == [1, 1, 2, 3, 3, 4, 5, 5, 6, 6], "Q() value error(s)"
print("Q(n) for n = [1..10] is:", ', '.join(str(i) for i in first10))
assert q(1000) == 502, "Q(1000) value error"
print("Q(1000) =", q(1000))

View file

@ -0,0 +1,19 @@
from sys import getrecursionlimit
def q1(n):
if n < 1 or type(n) != int: raise ValueError("n must be an int >= 1")
try:
return q.seq[n]
except IndexError:
len_q, rlimit = len(q.seq), getrecursionlimit()
if (n - len_q) > (rlimit // 5):
for i in range(len_q, n, rlimit // 5):
q(i)
ans = q(n - q(n - 1)) + q(n - q(n - 2))
q.seq.append(ans)
return ans
if __name__ == '__main__':
tmp = q1(100000)
print("Q(i+1) < Q(i) for i [1..100000] is true %i times." %
sum(k1 < k0 for k0, k1 in zip(q.seq[1:], q.seq[2:])))

View file

@ -0,0 +1,13 @@
def q(n):
l = len(q.seq)
while l <= n:
q.seq.append(q.seq[l - q.seq[l - 1]] + q.seq[l - q.seq[l - 2]])
l += 1
return q.seq[n]
q.seq = [None, 1, 1]
print("Q(n) for n = [1..10] is:", [q(i) for i in range(1, 11)])
print("Q(1000) =", q(1000))
q(100000)
print("Q(i+1) < Q(i) for i [1..100000] is true %i times." %
sum([q.seq[i] > q.seq[i + 1] for i in range(1, 100000)]))

View file

@ -0,0 +1,24 @@
/*REXX program to generate Hofstadter Q sequence for any N. */
q.=1 /*negative #s won't have values displayed.*/
call HofstadterQ 10
call HofstadterQ -1000; say; say '1000th value='result; say
call HofstadterQ -100000
downs=0; do j=2 to 100000; jm=j-1
downs=downs + (q.j<q.jm)
end /*j*/
say downs 'terms are less then the previous term.'
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────HofstadterQ subroutine──────────────*/
HofstadterQ: procedure expose q.; arg x 1 ox /*get the # to gen through*/
/*(above) OX is the same as X.*/
x=abs(x) /*use the absolute value for X. */
L=length(x) /*use for right justified output.*/
do j=1 for x
if j>2 then if q.j==1 then do; jm1=j-1; jm2=j-2
_1=j-q.jm1; _2=j-q.jm2
q.j=q._1+q._2
end
if ox>0 then say right(j,L) right(q.j,L) /*if X>0, tell*/
end /*j*/
return q.x /*return the Xth term to caller.*/

View file

@ -0,0 +1,23 @@
/*REXX program to generate Hofstadter Q sequence for any N. */
q.=1 /*negative #s won't have values displayed.*/
call HofstadterQ 10
call HofstadterQ -1000; say; say '1000th value='result; say
call HofstadterQ -100000
downs=0; do j=2 to 100000; jm=j-1
downs=downs + (q.j<q.jm)
end /*j*/
say downs 'terms are less then the previous term.'
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────HofstadterQ subroutine──────────────*/
HofstadterQ: procedure expose q.; arg x 1 ox /*get the # to gen through*/
/*(above) OX is the same as X.*/
x=abs(x) /*use the absolute value for X. */
L=length(x) /*use for right justified output.*/
do j=1 for x
if j>2 then if q.j==1 then q.j=q(j-q(j-1)) + q(j-q(j-2))
if ox>0 then say right(j,L) right(q.j,L) /*if X>0, tell*/
end /*j*/
return q.x /*return the Xth term to caller.*/
/*──────────────────────────────────Q subroutine────────────────────────*/
q: parse arg ?; return q.? /*return value of Q.? to invoker.*/

View file

@ -0,0 +1,25 @@
/*REXX program to generate Hofstadter Q sequence for any N. */
q.=0; q.1=1; q.2=1 /*negative #s won't have values displayed.*/
call HofstadterQ 10
call HofstadterQ -1000; say; say '1000th value='result; say
call HofstadterQ -100000
downs=0; do j=2 to 100000; jm=j-1
downs=downs + (q.j<q.jm)
end
say downs 'terms are less then the previous term.'
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────HofstadterQ subroutine──────────────*/
HofstadterQ: procedure expose q.; arg x 1 ox /*get the # to gen through*/
/*(above) OX is the same as X.*/
x=abs(x) /*use the absolute value for X. */
L=length(x) /*use for right justified output.*/
do j=1 for x
if q.j==0 then q.j=QR(j) /*Not defined? Then define it.*/
if ox>0 then say right(j,L) right(q.j,L) /*if X>0, tell*/
end /*j*/
return q.x /*return the Xth term to caller.*/
/*──────────────────────────────────QR subroutine───────────────────────*/
QR: procedure expose q.; parse arg n /*function is recursive. */
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. */

View file

@ -0,0 +1,16 @@
#lang racket
(define t (make-hash))
(hash-set! t 0 0)
(hash-set! t 1 1)
(hash-set! t 2 1)
(define (Q n)
(hash-ref! t n ( () (+ (Q (- n (Q (- n 1))))
(Q (- n (Q (- n 2))))))))
(for/list ([i (in-range 1 11)]) (Q i))
(Q 1000)
;; extra credit
(for/sum ([i 100000]) (if (< (Q (add1 i)) (Q i)) 1 0))

View file

@ -0,0 +1,22 @@
@cache = []
def Q(n)
if @cache[n].nil?
case n
when 1, 2 then @cache[n] = 1
else @cache[n] = Q(n - Q(n-1)) + Q(n - Q(n-2))
end
end
@cache[n]
end
puts "first 10 numbers in the sequence: #{(1..10).map {|n| Q(n)}}"
puts "1000'th term: #{Q(1000)}"
prev = Q(1)
count = 0
2.upto(100_000) do |n|
q = Q(n)
count += 1 if q < prev
prev = q
end
puts "number of times in the first 100,000 terms where Q(i)<Q(i-1): #{count}"

View file

@ -0,0 +1,8 @@
object HofstadterQseq extends App {
val Q: Int => Int = n => {
if (n <= 2) 1
else Q(n-Q(n-1))+Q(n-Q(n-2))
}
(1 to 10).map(i=>(i,Q(i))).foreach(t=>println("Q("+t._1+") = "+t._2))
println("Q("+1000+") = "+Q(1000))
}

View file

@ -0,0 +1,19 @@
object HofstadterQseq extends App {
val HofQ = scala.collection.mutable.Map((1->1),(2->1))
val Q: Int => Int = n => {
if (n < 1) 0
else {
val res = HofQ.keys.filter(_==n).toList match {
case Nil => {val v = Q(n-Q(n-1))+Q(n-Q(n-2)); HofQ += (n->v); v}
case xs => HofQ(n)
}
res
}
}
(1 to 10).map(i=>(i,Q(i))).foreach(t=>println("Q("+t._1+") = "+t._2))
println("Q("+1000+") = "+Q(1000))
println((3 to 100000).filter(i=>Q(i)<Q(i-1)).size)
}

View file

@ -0,0 +1,47 @@
(define qc '#(0 1 1))
(define filled 3)
(define len 3)
;; chicken scheme: vector-resize!
;; gambit: vector-append
(define (extend-qc)
(let* ((new-len (* 2 len))
(new-qc (make-vector new-len)))
(let copy ((n 0))
(if (< n len)
(begin
(vector-set! new-qc n (vector-ref qc n))
(copy (+ 1 n)))))
(set! len new-len)
(set! qc new-qc)))
(define (q n)
(let loop ()
(if (>= filled len) (extend-qc))
(if (>= n filled)
(begin
(vector-set! qc filled (+ (q (- filled (q (- filled 1))))
(q (- filled (q (- filled 2))))))
(set! filled (+ 1 filled))
(loop))
(vector-ref qc n))))
(display "Q(1 .. 10): ")
(let loop ((i 1))
;; (print) behave differently regarding newline across compilers
(display (q i))
(display " ")
(if (< i 10)
(loop (+ 1 i))
(newline)))
(display "Q(1000): ")
(display (q 1000))
(newline)
(display "bumps up to 100000: ")
(display
(let loop ((s 0) (i 1))
(if (>= i 100000) s
(loop (+ s (if (> (q i) (q (+ 1 i))) 1 0)) (+ 1 i)))))
(newline)

View file

@ -0,0 +1,3 @@
Q(1 .. 10): 1 1 2 3 3 4 5 5 6 6
Q(1000): 502
bumps up to 100000: 49798

View file

@ -0,0 +1,24 @@
package require Tcl 8.5
# Index 0 is not used, but putting it in makes the code a bit shorter
set tcl::mathfunc::Qcache {Q:-> 1 1}
proc tcl::mathfunc::Q {n} {
variable Qcache
if {$n >= [llength $Qcache]} {
lappend Qcache [expr {Q($n - Q($n-1)) + Q($n - Q($n-2))}]
}
return [lindex $Qcache $n]
}
# Demonstration code
for {set i 1} {$i <= 10} {incr i} {
puts "Q($i) == [expr {Q($i)}]"
}
# This runs very close to recursion limit...
puts "Q(1000) == [expr Q(1000)]"
# This code is OK, because the calculations are done step by step
set q [expr Q(1)]
for {set i 2} {$i <= 100000} {incr i} {
incr count [expr {$q > [set q [expr {Q($i)}]]}]
}
puts "Q(i)<Q(i-1) for i \[2..100000\] is true $count times"