Post Reply 
[VA] HP-71B Mini-challenge: Qualifying for a job
09-17-2022, 09:33 AM
Post: #21
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
(09-17-2022 09:20 AM)J-F Garnier Wrote:  ... or close your DEF FNG structure with END DEF followed by some code, that code will executed as part of the function FNZ.

J-F

Ah! Thanks for the explanation - now I could get the code to fail! I had fallen into the trap ... Wink

Cheers,
Thomas

[35/45/55/65/67/97/80 21/25/29C 31E/32E/33E|C/34C/38E 41C|CV|CX 71B 10C/11C/12C/15C|CE/16C 32S|SII/42S 28C|S 48GX/49G/50G 35S 41X]
Find all posts by this user
Quote this message in a reply
09-17-2022, 10:40 AM
Post: #22
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
(09-17-2022 09:05 AM)ThomasF Wrote:  Hm, maybe I missed something?

Me Too!
Fortunately, through your code, I discover something fundamental that I wish to share with all of you.

This challenge is really a coup de pied au cul. I discover that I did not understand how my HP-1B behave.

Thanks to your code, I realized something important: by using several nested DEF FN definitions, it needs as many END DEF to close all these up properly.
Any missing END DEF make the second part of the program included in the definition part and it will not be executed unless you explicitly type RUN 10 [End Line]!

If we copy the codes proposed by J-F Garnier or those of ThomasF, we expect that pressing the RUN key will display the time.

Try it! Is the time displayed? What happened?


Now type this version of the code where I deliberately add a few DISP instructions to trace on:

1 DEF FNZ @ DISP "Z" @ DEF FNS(N) @ IF N>0 THEN FNS=RND+FNS(N-1)
2 DISP "S";N @ END DEF @ DISP "ZZ" @ END DEF @ DEF FNO=1
3 DEF FNG=FNS(8)-4 @ DEF FND=IP(RND*6)+1

10 DISP DATE$&" "&TIME$


Set your DELAY at something practical, such as DELAY 1,.125 for example.

When you press the RUN key, current Date and Time are displayed immediately.
Notice that no "Z" nor any "S..." appears.
That's OK.

Try a reasonable FNS(10), display show live counts from S 0 to S 10 before displaying resulting random summation. No Time-Date Stample.
That's OK.

Try FNO or FND, the expected random result immediately appears.
That's OK.

Try FNG. Please notice the live count from S 0 to S 8 due to the FNS(8) call from FNG expression.
That's OK.

Now try FNZ, the Z and ZZ are briefly displayed before the expected 0 result.
Is that OK?
Are you sure?

Why doesn't any "S 0" (or any "S ..." depending of actual N value) appears??

Now, alter the line 2 of my code by changing the two END DEF into simple END.
Press the RUN key, did the Date and Time still display?
Did the function call FNS(4), FNO FND and FNG behave the same as previously?
Did the function call FNZ display any Z or ZZ ?

humm... humm...

Now restore the first END in line 2 into the original END DEF instruction and remove the second END.
Did RUN key display the date and time?
What's wrong with FNZ? Why did the Date and Time appears?

First:
From the point of view of the definition's structures, the two END are equivalent to the two END DEF instructions but there really END instruction that stop the running program before Date and Time display.

Second:
The END DEF instructions are needed when we nested user's function definitions.
That why no "S ..." were displayed when FNZ is evoked, the DISP "S";N is not part of the DEF FNZ definition block. The DEF FN structures are nested such like any FOR TO NEXT structures are.


I add colors to help interpratation of my code. each user function have a different color. Black remain for block-program level.

1 DEF FNZ @ DISP "Z" @ DEF FNS(N) @ IF N>0 THEN FNS=RND+FNS(N-1)
2 DISP "S";N @ END DEF @
DISP "ZZ" @ END DEF @ DEF FNO=1
3 DEF FNG=FNS(8)-4 @ DEF FND=IP(RND*6)+1

10 DISP DATE$&" "&TIME$


It's the amazing HP-71B.
No hint of how nested definitions are handled is made in The Reference Manual. However, this is indeed possible and has been thought out by the designers of this overpowered BASIC.

This is what I discover, it makes my day.
Find all posts by this user
Quote this message in a reply
09-17-2022, 11:44 AM
Post: #23
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
Hello!

Very interesting solutions and findings so far... however I must strongly object to some of the things I see here ;-) This thread is about applying for a job as a programmer. I have worked suffiently long in this field to know what is involved.

Using obscure and undocumented features of a calculator or programming language and shaving off two bytes by relying on possibly unitialised variables/functions (as in "... DEF FNZ @ DEF ...") will definitely not be helpful with your application...

I am looking forward to see Valentin's solution - as usual with his challenges.

Regards
Max
Find all posts by this user
Quote this message in a reply
09-17-2022, 12:44 PM
Post: #24
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
(09-16-2022 11:44 AM)J-F Garnier Wrote:  I'm still puzzled by the goal of the FNZ and FNO trivial functions, I don't see any way to make them simpler.

J-F

I have not had the time to look into this interesting challenge, but it occurred to me that the reason for including FNZ and FNO are to find some clever way to assign their values using the result of some other operation or assignment, this saving a few bytes?

--Bob Prosperi
Find all posts by this user
Quote this message in a reply
09-17-2022, 01:57 PM (This post was last modified: 09-17-2022 02:11 PM by J-F Garnier.)
Post: #25
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
.
Today I learnt something from this challenge:

Humility, never be too much sure of one's own knowledge

... because my solution is WRONG !

As in Diego's signature, "Do not suppose, check it twice."

It is true that END can be used to exit a multiline DEF structure.
But the DEF structure MUST be ended by END DEF !

For instance:
DEF FNF(X)
...
IF some condition THEN END ! exit FNF
...
END DEF

is correct.

So my new solution is, in exactly 92 bytes:

10 DEF FNS(N) @ IF N>0 THEN FNS=FNS(N-1)+RND
20 END DEF @ DEF FNG=FNS(8)+INX @ DEF FND=IP(1+RND*6) @ DEF FNZ=0 @ DEF FNO=1


J-F
Visit this user's website Find all posts by this user
Quote this message in a reply
09-20-2022, 03:59 PM
Post: #26
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
  
Hi, all,

Thanks to all of you who expressed interest in my HP-71B mini-challenge, namely J-F Garnier, C.Ret, ThomasF, KeithB, Dave Britten, rprosperi and Maximilan Hohmann, and most special thanks to those who provided code and analysis, much, much appreciated. Smile

J-F Garnier Wrote:
Quote:1 DEF FNZ @ DEF FNO=1

I'm starting to wonder if this was a deliberate trap set by Valentin. Smile

Indeed it was !. From the very start, I wanted to mislead would-be solutioners into stumbling upon this 92-byte decoy one-liner:
    1 DEF FNS(N) @ S=0 @ FOR I=1 TO N @ S=S+RND @ NEXT I @ FNS=S @ DEF FNG=FNS(8)-4 @ DEF FND=IP(RND*6+1) @ DEF FNZ @ DEF FNO=1
which must be entered without any spacing (and thus will later give a WRN: Line too long if attempting to edit it) as it requires exactly the maximum 95-char command line length. Some notes about it:
  • +INX can't be used instead of -4 because the line would then exceed 95 characters so it wouldn't fit in just one line.
      
  • IP(RND*6+1) can't be replaced by CEIL(RND*6) because (although extremely improbable) RND can return an exact zero value and then CEIL(RND*6) would evaluate to 0, which is not a valid die value.
      
  • FNS doesn't use recursion to compute the sum of the N random values but it uses simple iteration instead, which is faster and takes a very small, fixed amount of RAM. Initially I was intent in making recursion unusable in the solutions by simply including something like this as a sample run:

             >RANDOMIZE 1 @ FNS(100000) -> 49948.1804242

    which gives no problem to the iterative definition but would be totally unfeasible for the recursive definition, which would simply result in an Insufficient memory error. However, I liked the recursive definition and wanted people to find it out and use it in their solutions so I didn't include such large-N sample runs, in order to make it viable.
      
  • Finally, the trap. As written, the one-liner decoy would work Ok and be a correct solution IF no other executable code follows it. It seems to work perfectly, but there's an END DEF statement missing (actually, two) and the moment you add additional code after it (say, 2 DISP "Main program initialization follows ..."), your're going to encounter incorrect, unexpected behaviour, as some of you did.

    To ensure that such puzzling behavior was bound to be encountered I included this line in my OP:

      "She also mentioned that eventually your code would be immediately followed by some main-program initialization code written by another applicant."

    thus turning into non-solutions the decoy one-liner and any other solutions lacking the necessary END DEF statement(s) required by multi-line user-defined functions followed by arbitrary executable code.

That was the trap and many of you fell for it though, clever people that you are, you eventually analyzed it all and came to the right conclusions and correct solutions. Well done, congratulations ! Smile

As for my original solution, it's a 92-byte affair virtually identical to J-F Garnier's (who really nailed it) and other people's as well, namely:
    1 DEF FNS(N) @ IF N>0 THEN FNS=FNS(N-1)+RND
    2 END DEF @ DEF FNG=FNS(8)+INX @ DEF FND=IP(RND*6+1) @ DEF FNZ=0 @ DEF FNO=1
the only "difference" being that I used IP(RND*6+1) while J-F used IP(1+RND*6). Also, as explained above for the decoy one-liner, in purity the IP(...) can't be replaced by CEIL(RND*6), which would shorten the solution by 2 bytes, lest you'll get a 0 die throw once in a while, namely after 500-billion simulated throws on average ! Smile

That's all. Thank you very much for your interest, appreciation, analysis and solutions, I really hope you enjoyed it all and if furthermore you learned something new, so much the better. But don't think that your application process is over, just wait for Part 2 to be posted soon, stay tuned !

Best regards.
V.

  
All My Articles & other Materials here:  Valentin Albillo's HP Collection
 
Visit this user's website Find all posts by this user
Quote this message in a reply
09-20-2022, 08:36 PM (This post was last modified: 09-20-2022 08:37 PM by Dave Britten.)
Post: #27
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
Out of curiosity, are there situations where ending a multi-statement function with END instead of END DEF will have unintended consequences? I could swear I read a tip that you can just use END, but for the life of me, I can't remember where...
Visit this user's website Find all posts by this user
Quote this message in a reply
09-21-2022, 06:44 AM
Post: #28
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
(09-20-2022 08:36 PM)Dave Britten Wrote:  Out of curiosity, are there situations where ending a multi-statement function with END instead of END DEF will have unintended consequences?

I made the same mistake so I can answer...

Here is a simple example
10 DEF FNF
20 DISP "here L20"
30 END
40 DISP "here L40"

If you try FNF, all seems to be fine.
But if you run the program, you should expect to see "here L40" as part of the main program.
You will not because the multiline DEF FNF structure is not closed, and so skipped by the interpreter.
Replacing the END by END DEF fixes it.

The HP-71 reference manual may be misleading, but if read carefully it is exact and clear:
- in the END DEF section, we can read:
"When used in a user-defined function, END and DESTROY ALL operate in the same way as END DEF."
This is the misleading part, we can wrongly interpret it as END and END DEF being equivalent to close the DEF structure.
It's not true, it just means that END (used inside a user-defined function) exits the DEF FN structure as END DEF does.
- in the DEF FN section, it is clearly stated:
"A DEF FN statement with no = symbol is the beginning of a multiple-statement function definition that must have a corresponding END DEF statement."

J-F
Visit this user's website Find all posts by this user
Quote this message in a reply
09-22-2022, 08:11 AM
Post: #29
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
A few more comments about the challenge:

First of all, thanks Valentin for it!
At first glance, it looked easy and just a matter of optimizing a single summation operation, but clearly it was not !

Nested User-Defined-Functions (UDF)
The challenge made me realize that UDFs can be nested, for instance:
10 DEF FNF(X)
20 DEF FNG(Y)
30 FNG=X+Y
40 END DEF
50 FNF=FNG(2*X)
60 END DEF
is a valid construction on the 71B.
But there is no benefit to do so. The inner UDF is still visible from the main program, and can't access the outer UDF local parameters: X in line 30 is not the local FNF parameter, but variable X of the main program environment.
All works as if the 2 UDFs were independent.
Actually, nested UDFs are explicitly forbidden on the Technical BASIC close variants of the HP-75 and Series 80 computers.
Why is it allowed on the HP-71B? Maybe just because it was possible and doesn't harm but it's better not to use this "feature" on the HP-71B, for clarity.

Can RND be zero?
Valentin mentioned that the solution could be shorten by using CEIL(RND*6) instead of IP(RND*6+1). I also considered this option, and I too discarded it because the HP-71 reference manual states that the RND result r is 0<= r <1.
However, a close inspection of the internal working of RND shows that it is not possible to get a zero value from RND (except if RANDOMIZE 0, an uninteresting trivial case).
I will open a new topic to discuss this point in detail.

J-F
Visit this user's website Find all posts by this user
Quote this message in a reply
09-22-2022, 01:19 PM
Post: #30
RE: [VA] HP-71B Mini-challenge: Qualifying for a job
This is quickly turning into an obfuscated BASIC programming contest. Next you know we will implement something like Duff's Device:
https://c-faq.com/misc/duff.html
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: 3 Guest(s)