GS The Recaman's sequence is a sequence invented by Bernardo Recaman Santos (a Colombian mathematician). It is defined by :
a(0) = 0 a(n) = a(n-1) - n for n > 0, if positive and not already in the sequence a(n) = a(n-1) + n otherwise
The first terms of the sequence are:
0, 1, 3, 6, 2, 7, 13, 20, 12, 21, 11, 22, 10, 23, 9, 24, 8, 25, 43, 62, 42, 63, 41, 18, 42, 17, 43, 16, 44, 15, 45, 14, 46, 79, ....
An interesting visualization of this sequence can be done with half-circle representing the jump from a(n) to a(n+1).
The idea of plotting the Recaman sequence like this come from the YouTube channel Numberphile in a video featuring Alex Bellos and Edmund Harriss.
With n = 100 :
With n = 200 :
# recaman.tcl
# Author: Gerard Sookahet
# Date: 15 Apr 2021
# Description: Plot Recaman sequence with half-circles
# Reference : Numberphile - https://www.youtube.com/watch?v=FGC5TdIiT9U
package require Tk
bind all <Escape> {exit}
proc recaman {n} {
if {$n <= 0} return
set s {}
lappend s 0
set prev 0
for {set i 1} {$i <= $n} {incr i} {
set curr [expr {$prev - $i}]
if {$curr < 0 || $curr in $s} then {set curr [expr {$prev + $i}]}
lappend s $curr
set prev $curr
}
return $s
}
proc plot_recaman {s} {
set n [llength $s]
incr n -1
set z 4
set H [expr {4*$n}]
if {$n > 100} then {
set z 2
set H [expr {2*$n}]
}
set W [expr {9*$n}]
set n2 [expr {$H/2}]
pack [canvas .c -background black -width $W -height $H]
pack [button .b -text Quit -command exit]
set x1 0
for {set i 1} {$i <= $n} {incr i} {
set x2 [expr {$z*[lindex $s $i]}]
set xo [expr {($x2 - $x1)/2}]
if {$i % 2 == 0} then {
set y1 [expr {$n2 - $xo}]
set y2 [expr {$n2 + $xo}]
set ext 180
} else {
set y1 [expr {$n2 + $xo}]
set y2 [expr {$n2 - $xo}]
set ext -180
}
.c create arc $x1 $y1 $x2 $y2 -extent $ext -style arc -outline blue
set x1 $x2
}
}
plot_recaman [recaman 100]Reference :
- Numberphile - https://www.youtube.com/watch?v=FGC5TdIiT9U
For those who estimate codegolfing [L1 ] :
proc R n {lappend L [expr {$n?[set x [lindex [set L [A [expr $n-1]]] e]]>$n&$x-$n ni$L?$x-$n:$x+$n:0}]}much faster (ten times!!) Recaman Sequence implementation. the code can also be easily converted for the coroutines/generator
proc recaman { total } {
if { $total <= 0 } {
return {}
}
set recaman {}
array set unused {} ; # unused numbers
set maxnum 1 ; # max of unused +1
set current 0
for { set i 1 } { $i<$total } { incr i } {
set n [ expr { $current - $i } ]
if { $n > 0 && [ info exists unused($n) ] } {
unset unused($n)
} else {
set n [ expr { $current + $i } ]
if { $n >= $maxnum } {
for { set maxnum } { $maxnum < $n } { incr maxnum } {
set unused($maxnum) $maxnum
}
incr maxnum
} else {
if { [ info exists unused($n) ] } {
unset unused($n)
} else {
# puts "dup $n"
}
}
}
set current $n
lappend recaman $n
}
set recaman
}