A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
14
Task/Hofstadter-Q-sequence/0DESCRIPTION
Normal file
14
Task/Hofstadter-Q-sequence/0DESCRIPTION
Normal 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).
|
||||
|
|
@ -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))
|
||||
)
|
||||
22
Task/Hofstadter-Q-sequence/AWK/hofstadter-q-sequence.awk
Normal file
22
Task/Hofstadter-Q-sequence/AWK/hofstadter-q-sequence.awk
Normal 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;
|
||||
}
|
||||
59
Task/Hofstadter-Q-sequence/Ada/hofstadter-q-sequence.ada
Normal file
59
Task/Hofstadter-Q-sequence/Ada/hofstadter-q-sequence.ada
Normal 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;
|
||||
|
|
@ -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%)
|
||||
21
Task/Hofstadter-Q-sequence/C++/hofstadter-q-sequence.cpp
Normal file
21
Task/Hofstadter-Q-sequence/C++/hofstadter-q-sequence.cpp
Normal 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 ;
|
||||
}
|
||||
64
Task/Hofstadter-Q-sequence/C-sharp/hofstadter-q-sequence.cs
Normal file
64
Task/Hofstadter-Q-sequence/C-sharp/hofstadter-q-sequence.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Task/Hofstadter-Q-sequence/C/hofstadter-q-sequence.c
Normal file
24
Task/Hofstadter-Q-sequence/C/hofstadter-q-sequence.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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)))
|
||||
|
|
@ -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
|
||||
|
|
@ -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)))
|
||||
17
Task/Hofstadter-Q-sequence/D/hofstadter-q-sequence-1.d
Normal file
17
Task/Hofstadter-Q-sequence/D/hofstadter-q-sequence-1.d
Normal 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)));
|
||||
}
|
||||
23
Task/Hofstadter-Q-sequence/D/hofstadter-q-sequence-2.d
Normal file
23
Task/Hofstadter-Q-sequence/D/hofstadter-q-sequence-2.d
Normal 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)));
|
||||
}
|
||||
|
|
@ -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)}");
|
||||
}
|
||||
42
Task/Hofstadter-Q-sequence/Dart/hofstadter-q-sequence-2.dart
Normal file
42
Task/Hofstadter-Q-sequence/Dart/hofstadter-q-sequence-2.dart
Normal 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");
|
||||
}
|
||||
17
Task/Hofstadter-Q-sequence/Dart/hofstadter-q-sequence-3.dart
Normal file
17
Task/Hofstadter-Q-sequence/Dart/hofstadter-q-sequence-3.dart
Normal 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");
|
||||
}
|
||||
30
Task/Hofstadter-Q-sequence/Erlang/hofstadter-q-sequence.erl
Normal file
30
Task/Hofstadter-Q-sequence/Erlang/hofstadter-q-sequence.erl
Normal 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).
|
||||
|
|
@ -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
|
||||
46
Task/Hofstadter-Q-sequence/Go/hofstadter-q-sequence.go
Normal file
46
Task/Hofstadter-Q-sequence/Go/hofstadter-q-sequence.go
Normal 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))
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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))
|
||||
|
|
@ -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
|
||||
39
Task/Hofstadter-Q-sequence/Icon/hofstadter-q-sequence.icon
Normal file
39
Task/Hofstadter-Q-sequence/Icon/hofstadter-q-sequence.icon
Normal 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
|
||||
8
Task/Hofstadter-Q-sequence/J/hofstadter-q-sequence-1.j
Normal file
8
Task/Hofstadter-Q-sequence/J/hofstadter-q-sequence-1.j
Normal 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
|
||||
)
|
||||
6
Task/Hofstadter-Q-sequence/J/hofstadter-q-sequence-2.j
Normal file
6
Task/Hofstadter-Q-sequence/J/hofstadter-q-sequence-2.j
Normal 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
|
||||
46
Task/Hofstadter-Q-sequence/Java/hofstadter-q-sequence.java
Normal file
46
Task/Hofstadter-Q-sequence/Java/hofstadter-q-sequence.java
Normal 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");
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
|
|
@ -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;
|
||||
|
|
@ -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:
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
> seq( Q( i ), i = 1 .. 10 );
|
||||
1, 1, 2, 3, 3, 4, 5, 5, 6, 6
|
||||
|
||||
> Q( 1000 );
|
||||
502
|
||||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
> Qflips( 10^5 );
|
||||
49798
|
||||
|
|
@ -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]]
|
||||
]
|
||||
|
|
@ -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
|
||||
21
Task/Hofstadter-Q-sequence/Perl/hofstadter-q-sequence.pl
Normal file
21
Task/Hofstadter-Q-sequence/Perl/hofstadter-q-sequence.pl
Normal 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";
|
||||
|
|
@ -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)))) ) ) ) )
|
||||
|
|
@ -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
|
||||
16
Task/Hofstadter-Q-sequence/Python/hofstadter-q-sequence-1.py
Normal file
16
Task/Hofstadter-Q-sequence/Python/hofstadter-q-sequence-1.py
Normal 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))
|
||||
19
Task/Hofstadter-Q-sequence/Python/hofstadter-q-sequence-2.py
Normal file
19
Task/Hofstadter-Q-sequence/Python/hofstadter-q-sequence-2.py
Normal 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:])))
|
||||
13
Task/Hofstadter-Q-sequence/Python/hofstadter-q-sequence-3.py
Normal file
13
Task/Hofstadter-Q-sequence/Python/hofstadter-q-sequence-3.py
Normal 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)]))
|
||||
24
Task/Hofstadter-Q-sequence/REXX/hofstadter-q-sequence-1.rexx
Normal file
24
Task/Hofstadter-Q-sequence/REXX/hofstadter-q-sequence-1.rexx
Normal 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.*/
|
||||
23
Task/Hofstadter-Q-sequence/REXX/hofstadter-q-sequence-2.rexx
Normal file
23
Task/Hofstadter-Q-sequence/REXX/hofstadter-q-sequence-2.rexx
Normal 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.*/
|
||||
25
Task/Hofstadter-Q-sequence/REXX/hofstadter-q-sequence-3.rexx
Normal file
25
Task/Hofstadter-Q-sequence/REXX/hofstadter-q-sequence-3.rexx
Normal 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. */
|
||||
16
Task/Hofstadter-Q-sequence/Racket/hofstadter-q-sequence.rkt
Normal file
16
Task/Hofstadter-Q-sequence/Racket/hofstadter-q-sequence.rkt
Normal 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))
|
||||
22
Task/Hofstadter-Q-sequence/Ruby/hofstadter-q-sequence.rb
Normal file
22
Task/Hofstadter-Q-sequence/Ruby/hofstadter-q-sequence.rb
Normal 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}"
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
47
Task/Hofstadter-Q-sequence/Scheme/hofstadter-q-sequence-1.ss
Normal file
47
Task/Hofstadter-Q-sequence/Scheme/hofstadter-q-sequence-1.ss
Normal 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)
|
||||
|
|
@ -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
|
||||
24
Task/Hofstadter-Q-sequence/Tcl/hofstadter-q-sequence.tcl
Normal file
24
Task/Hofstadter-Q-sequence/Tcl/hofstadter-q-sequence.tcl
Normal 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"
|
||||
Loading…
Add table
Add a link
Reference in a new issue