Talk:Hofstadter Figure-Figure sequences: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎timings for the REXX solutions: removed STYLE from the PRE html tag.)
m (→‎timings for the REXX solutions: replaced the REXX program, updated the timings.)
Line 34: Line 34:


I normally don't including timings for the REXX solutions that I post, but when I saw the 2<sup>nd</sup> REXX example's timings,
I normally don't including timings for the REXX solutions that I post, but when I saw the 2<sup>nd</sup> REXX example's timings,

<br>I decided to go back and include the timings here as the 2<sup>nd</sup> example's timings seemed a bit high.
I decided to go back and include the timings here as the 2<sup>nd</sup> example's timings seemed a bit high.
<br><br>I didn't expect a difference of magnitude.

<lang rexx>/*REXX pgm to calculate & verify the Hofstadter Figure-Figure sequences.*/
<br>I didn't expect a difference of magnitude.
<lang rexx>/*REXX pgm calculates & verifies the Hofstadter Figure-Figure sequences.*/
call time 'Reset'
call time 'Reset'
parse arg x highV . /*obtain any C.L. specifications.*/
parse arg x high bot . /*obtain any C.L. specifications.*/
if x=='' then x=10; if highV=='' then highV=1000 /*use the defaults?*/
if x=='' then x=10; if high=='' then high=1000 /*use the defaults?*/
low=1 /*use unity as the starting point*/
if bot=='' then bot=40 /* " " " */
if x<0 then low=abs(x) /*only show a single │X│ value.*/
low=1; if x<0 then low=abs(x) /*only show a single │X│ value.*/
r.=0; r.1=1; rr.=r.; rr.1=1 /*initialize the R and RR arrays.*/
r.=0; r.1=1; rr.=r.; rr.1=1 /*initialize the R & RR arrays.*/
s.=0; s.1=2; ss.=s.; ss.2=1 /* " " S " SS " .*/
s.=0; s.1=2 /* " " S array. */
errs=0
errs=0; $.=0
do i=low to abs(x) /*show first X values of R & S */
do i=low to abs(x) /*show first X values of R & S */
say right('R('i") =",20) right(ffr(i),7), /*show nice*/
say right('R('i") =",20) right(ffr(i),7), /*show nice*/
right('S('i") =",20) right(ffs(i),7) /* R & S */
right('S('i") =",20) right(ffs(i),7) /* R & S */
end /*i*/
end /*i*/
if x<1 then exit /*if x 0, then we're all done.*/

do m=1 for bot; r=ffr(m); $.r=1; end /*calculate 1st 40 R values.*/

@='duplicate number in R and S lists:' /* [↓] calc. 1st 960 S values.*/
do n=1 for high-bot; s=ffs(n); if $.s then call sErr @ s; $.s=1; end

/* [↓] verify all 1≤#≤1k present*/
do v=1 for high; if \$.v then call sErr 'missing R │ S:' v; end
say 'took' format(time('Elapsed'),,2) "seconds."
say 'took' format(time('Elapsed'),,2) "seconds."
if x<1 then exit /*stick a fork in it, we're done.*/
/*═══════════════════════════════════════verify 1st 1k: unique & present*/
both.=0 /*initialize the BOTH array. */
/*build list of 1st 40 R values.*/
do m=1 for 40; r=ffr(m) /*calculate 1st 40 R values.*/
both.r=1 /*build the BOTH array. */
end /*m*/
/*build list of 1st 960 S values.*/
do n=1 for 960; s=ffs(n) /*calculate 1st 960 S values.*/
if both.s then call sayErr 'duplicate number in R and S lists:' s
both.s=1 /*add to the BOTH array. */
end /*n*/
/*verify presence and uniqueness.*/
do v=1 for highV /*verify all 1 ≤ # ≤ 1k present.*/
if \both.v then call sayErr 'missing R │ S:' v
end /*v*/
say
say
@v='verification'; @i=" [inclusive]." /*shortcuts to shorten prog width*/
if errs==0 then say 'verification completed for all numbers from 1 ──►' high " [inclusive]."
else say 'verification failed with' errs "errors."
if errs==0 then say @v 'completed for all numbers from 1 ──►' highV @i
else say @v 'failed with' errs "errors."
say 'took' format(time('E'),,2) "seconds."
exit /*stick a fork in it, we're done.*/
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────FFR subroutine──────────────────────*/
/*──────────────────────────────────FFR subroutine──────────────────────*/
ffr: procedure expose r. s. rr. ss.; parse arg n
ffr: procedure expose r. s. rr.; parse arg n
if r.n\==0 then return r.n /*Defined? Then return the value.*/
if r.n\==0 then return r.n /*Defined? Then return the value.*/
_=ffr(n-1) + ffs(n-1) /*calculate the FFR value. */
_=ffr(n-1) + ffs(n-1) /*calculate the FFR value. */
r.n=_; rr._=1 /*assign the value to R and RR.*/
r.n=_; rr._=1; return _ /*assign value to R & RR; return.*/
return _ /*return the value to the invoker*/
/*──────────────────────────────────FFS subroutine──────────────────────*/
/*──────────────────────────────────FFS subroutine──────────────────────*/
ffs: procedure expose r. s. rr. ss.; parse arg n
ffs: procedure expose r. s. rr.; parse arg n /*search for ¬null R│S #.*/
do k=1 for n while s.n==0 /*search for not null R S num.*/
if s.n==0 then do k=1 for n /* [↓] 1st IF is a short circuit*/
if s.k\==0 then if ffr(k)\==0 then iterate /*short circuit*/
if s.k\==0 then if ffr(k)\==0 then iterate
km=k-1; _=s.km+1 /*the next SS number, possibly.*/
km=k-1; _=s.km+1 /*the next SS number, possibly.*/
_=_+rr._ /*maybe adjust for the FRR num.*/
_=_+rr._; s.k=_ /*define an element of S array.*/
s.k=_; ss._=1 /*define couple of FFS numbers.*/
end /*k*/
end /*k*/
return s.n /*return the value to the invoker*/
/*──────────────────────────────────SERR subroutine─────────────────────*/
return s.n /*return the value to the invoker*/
sErr: errs=errs+1; say '***error***!' arg(1); return</lang>
/*──────────────────────────────────SAYERR subroutine───────────────────*/
sayErr: errs=errs+1; say; say '***error***!'; say; say arg(1); say; return</lang>
'''output''' when using the defaults:
'''output''' when using the defaults:
<pre>
<pre>
Line 104: Line 95:


verification completed for all numbers from 1 ──► 1000 [inclusive].
verification completed for all numbers from 1 ──► 1000 [inclusive].
took 1.58 seconds.
took 1.52 seconds.
</pre>
</pre>
The (above) example was run under Windows 7 on a HP box (3.2GHz) using Regina.
The (above) example was run under Windows 7 on a HP box (3.2GHz) using Regina.

Revision as of 20:49, 21 May 2015

No max n

That statement is there to explicitly exclude solutions that used a fixed sized array, say of a 1000 elements and an empty array, then moved elements between the two arrays.

Mind you, an algorithm that started with fixed array sizes and doubled their sizes as necessary would be OK. --Paddy3118 08:37, 22 October 2011 (UTC)

S(n)

The sequence S(n) is further defined as the sequence of positive integers not present in R(n).

I think this should be S(n) is defined as the nth integer in the sequence of positive integers not present in R(n). If S(n) is itself a sequence then R(n) would be a sequence, but the example R(n) values suggest that R is a sequence and R(n) is an integer from that sequence. --Rdm 16:34, 22 October 2011 (UTC)

Hmm. You're right, but then I can't help but think that S(n) can stand for both an integer given a particular value of n, or the sequence when thinking of n as being an arbitrary value? It seems to me that it can be either or both, but either way, would you go further and say that you could not determine the meaning of the sentence?
I'm inclined to leave it as-is. --Paddy3118 17:44, 22 October 2011 (UTC)
In the general case, yes, we might use S(n) to refer to a sequence. However, for this to be accurate, n needs to be an unbound value. And in that particular sentence, we are talking about n having a specific value (which is used in R(n)). Anyways, from my point of view the phrasing is confusing (and opens up questions like: is it possible for S(n) to contain values for some value of n which are not present in later values of n? And rather than delve into the issues that I would need to tackle to determine whether or not this could be a relevant topic, I would rather the notation be self consistent). --Rdm 17:56, 22 October 2011 (UTC)
Not really, this aspect of the definition is present in the references too. I suspect that it may be a part of the original description cited as: D. Hofstadter, "Gödel, Escher, Bach", p. 73, but I don't have it to hand at the moment to check. When I first saw their definition I found it confusing at first too, but that is what made it interesting when trying to code it.
When I had finished the Python version I checked it with tables of the first 1000 values refered to from Sloane: here for R and here for S, although the table for S has an off-by-one error. --Paddy3118 18:31, 22 October 2011 (UTC)
Another ref. with a similar definition: CRC concise encyclopedia of mathematics By Eric W. Weisstein pp 1385. --Paddy3118 18:40, 22 October 2011 (UTC)
Ok, well, I think that's sloppy use of terminology, but I suppose that if they are not considering any possibilities involving sequences of sequences that the sloppiness becomes invisible. --Rdm 19:08, 23 October 2011 (UTC)
It is pretty common to say "S(n)" while meaning "sequence S with n denoting its index", and it's unambiguous. For one thing, the very first sentence already said "sequence of positive integers", which is pretty impossible to be misunderstood as "sequence of sequences of integers". This is how human discuss math using a natural language, there's no need to exercise a context-free parser here. --Ledrug 20:11, 23 October 2011 (UTC)
That's not the issue. S(n) would still be an integer sequence if S was a sequence of sequences. After some thought, though, this appears to be an equivalent interpretation. --Rdm 11:32, 24 October 2011 (UTC)

Factor solution

Marked incorrect as the task asks that particular ranges of values of ffr and ffs be collected and compared to the range of integers 1..1000. The current solution starts of by ignoring ffr and ffs then assuming that the first 1000 values of something are equal to ... --Paddy3118 19:46, 8 December 2011 (UTC)

timings for the REXX solutions

I normally don't including timings for the REXX solutions that I post, but when I saw the 2nd REXX example's timings,

I decided to go back and include the timings here as the 2nd example's timings seemed a bit high.


I didn't expect a difference of magnitude. <lang rexx>/*REXX pgm calculates & verifies the Hofstadter Figure-Figure sequences.*/ call time 'Reset' parse arg x high bot . /*obtain any C.L. specifications.*/ if x== then x=10; if high== then high=1000 /*use the defaults?*/ if bot== then bot=40 /* " " " */ low=1; if x<0 then low=abs(x) /*only show a single │X│ value.*/ r.=0; r.1=1; rr.=r.; rr.1=1 /*initialize the R & RR arrays.*/ s.=0; s.1=2 /* " " S array. */ errs=0; $.=0

                 do i=low  to abs(x)  /*show first X values of  R & S  */
                 say right('R('i") =",20) right(ffr(i),7),  /*show nice*/
                     right('S('i") =",20) right(ffs(i),7)   /*  R & S  */
                 end   /*i*/

if x<1 then exit /*if x ≤ 0, then we're all done.*/

  do m=1 for  bot; r=ffr(m); $.r=1; end    /*calculate 1st 40 R values.*/

@='duplicate number in R and S lists:' /* [↓] calc. 1st 960 S values.*/

  do n=1 for high-bot;  s=ffs(n); if $.s  then call sErr @ s;  $.s=1; end
                                      /* [↓]  verify all 1≤#≤1k present*/
  do v=1  for high;  if \$.v  then  call sErr  'missing R │ S:'  v;   end

say 'took' format(time('Elapsed'),,2) "seconds." say if errs==0 then say 'verification completed for all numbers from 1 ──►' high " [inclusive]."

           else say 'verification failed with'      errs      "errors."

exit /*stick a fork in it, we're done.*/ /*──────────────────────────────────FFR subroutine──────────────────────*/ ffr: procedure expose r. s. rr.; parse arg n if r.n\==0 then return r.n /*Defined? Then return the value.*/ _=ffr(n-1) + ffs(n-1) /*calculate the FFR value. */ r.n=_; rr._=1; return _ /*assign value to R & RR; return.*/ /*──────────────────────────────────FFS subroutine──────────────────────*/ ffs: procedure expose r. s. rr.; parse arg n /*search for ¬null R│S #.*/ if s.n==0 then do k=1 for n /* [↓] 1st IF is a short circuit*/

               if s.k\==0  then  if ffr(k)\==0  then iterate
               km=k-1;     _=s.km+1   /*the next  SS  number, possibly.*/
               _=_+rr._;   s.k=_      /*define an element of  S  array.*/
               end    /*k*/

return s.n /*return the value to the invoker*/ /*──────────────────────────────────SERR subroutine─────────────────────*/ sErr: errs=errs+1; say '***error***!' arg(1); return</lang> output when using the defaults:

              R(1) =       1               S(1) =       2
              R(2) =       3               S(2) =       4
              R(3) =       7               S(3) =       5
              R(4) =      12               S(4) =       6
              R(5) =      18               S(5) =       8
              R(6) =      26               S(6) =       9
              R(7) =      35               S(7) =      10
              R(8) =      45               S(8) =      11
              R(9) =      56               S(9) =      13
             R(10) =      69              S(10) =      14
took 0.00 seconds.

verification completed for all numbers from  1 ──► 1000   [inclusive].
took 1.52 seconds.

The (above) example was run under Windows 7 on a HP box (3.2GHz) using Regina.