|
Post by David Drake on Jan 29, 2020 15:19:02 GMT -5
For a fun exercise I attempted to create a fully-functioning RPN calculator with as little code as possible. The result is the little gem below: only 1,446 characters. Can anyone make it even smaller? Reminds me of the days of GWBASIC when every character counted.
Cheers!
David
nomainwin:global K$:WindowWidth=165:WindowHeight=200
textbox #1.t,5,1,142,25
button #1.c," C ",[c],UL,5,27
button #1.a,"+/-",[a],UL,40,27
button #1.r," % ",[r],UL,75,27
button #1.d," / ",[d],UL,110,27
button #1.7," 7 ",[7],UL,5,53
button #1.8," 8 ",[8],UL,40,53
button #1.9," 9 ",[9],UL,75,53
button #1.x," x ",[x],UL,110,53
button #1.4," 4 ",[4],UL,5,79
button #1.5," 5 ",[5],UL,40,79
button #1.6," 6 ",[6],UL,75,79
button #1.m," - ",[z],UL,110,79
button #1.1," 1 ",[1],UL,5,105
button #1.2," 2 ",[2],UL,40,105
button #1.3," 3 ",[3],UL,75,105
button #1.p," + ",[y],UL,110,105
button #1.0," 0 ",[0],UL,5,131
button #1.o," . ",[w],UL,40,131
button #1.e," Enter ",[e],UL,78,131
open""for window as #1:#1 "trapclose [q]":wait
[c] K$="":call u,K$:wait
[a]if K$="" then L$=str$(-1*val(L$)):call u,L$
if K$<>"" then K$=str$(-1*val(K$)):call u,K$
wait
[r] L$=str$(val(L$)*100):call u,L$:K$="":wait
[d] if val(K$)<>0 then
S=val(L$)/val(K$):L$=str$(S):K$=""
else
K$="":L$="error"
end if
call u,L$:wait
[7] call k,"7":wait
[8] call k,"8":wait
[9] call k,"9":wait
[x] S=val(L$)*val(K$):L$=str$(S):K$="":call u,L$:wait
[4] call k,"4":wait
[5] call k,"5":wait
[6] call k,"6":wait
[z] S=val(L$)-val(K$):L$=str$(S):K$="":call u,L$:wait
[1] call k,"1":wait
[2] call k,"2":wait
[3] call k,"3":wait
[y] S=val(L$)+val(K$):L$=str$(S):K$="":call u,L$:wait
[0] call k,"0":wait
[w] call k,".":wait
[e] if K$=""then K$=L$
L$=K$:K$="":call u,L$:wait
[q] close #1:end
sub u D$
#1.t,D$
end sub
sub k E$
K$=K$+E$:call u,K$
end sub
|
|
|
Post by Carl Gundel on Jan 29, 2020 16:19:08 GMT -5
For a fun exercise I attempted to create a fully-functioning RPN calculator with as little code as possible. The result is the little gem below: only 1,446 characters. Can anyone make it even smaller? Reminds me of the days of GWBASIC when every character counted. Cheers! Does it fit in 1K? Edit: Oh, I see. 1,446 bytes.
|
|
|
Post by tenochtitlanuk on Jan 29, 2020 18:06:48 GMT -5
Fun. Still have my Sinclair Scientific from 1974 which introduced me to RPN. Love its simplicity, which also got me into Forth.
|
|
|
Post by tsh73 on Jan 29, 2020 18:18:00 GMT -5
Doesn't RPN calculator supposed to support bigger stack, for things like
1 2 3 * + ?
|
|
|
Post by Carl Gundel on Jan 29, 2020 19:36:21 GMT -5
Doesn't RPN calculator supposed to support bigger stack, for things like 1 2 3 * + ? RPN can have as big a stack as you like.
|
|
|
Post by Carl Gundel on Jan 29, 2020 19:37:31 GMT -5
Fun. Still have my Sinclair Scientific from 1974 which introduced me to RPN. Love its simplicity, which also got me into Forth. I had the programmable version of that one. I actually learned RPN on my father's HP-67. That also led me into Forth.
|
|
|
Post by Carl Gundel on Jan 29, 2020 20:08:06 GMT -5
For a fun exercise I attempted to create a fully-functioning RPN calculator with as little code as possible. The result is the little gem below: only 1,446 characters. Can anyone make it even smaller? Reminds me of the days of GWBASIC when every character counted. Cheers! David For some reason your posted version with the extra blank lines removed counts as 1,559 bytes for me? Here is my version which comes to 1,478 bytes. There are also spaces which can be removed. I didn't bother. I do wonder if this can be done in 1K. nomainwin:global K$:WindowWidth=165:WindowHeight=200 textbox #1.t,5,1,142,25 button #1.c," C ",[c],UL,5,27 button #1.a,"+/-",[a],UL,40,27 button #1.r," % ",[r],UL,75,27 button #1.d," / ",[d],UL,110,27 button #1.7," 7 ",[7],UL,5,53 button #1.8," 8 ",[8],UL,40,53 button #1.9," 9 ",[9],UL,75,53 button #1.x," x ",[x],UL,110,53 button #1.4," 4 ",[4],UL,5,79 button #1.5," 5 ",[5],UL,40,79 button #1.6," 6 ",[6],UL,75,79 button #1.m," - ",[z],UL,110,79 button #1.1," 1 ",[1],UL,5,105 button #1.2," 2 ",[2],UL,40,105 button #1.3," 3 ",[3],UL,75,105 button #1.p," + ",[y],UL,110,105 button #1.0," 0 ",[0],UL,5,131 button #1.o," . ",[w],UL,40,131 button #1.e," Enter ",[e],UL,78,131 open""for window as #1:#1 "trapclose [q]":wait [c] K$="":call u,K$:wait [a]if K$="" then L$=str$(0-val(L$)):call u,L$ else K$=str$(0-val(K$)):call u,K$ wait [r] L$=str$(val(L$)*100):goto [U] [d] if val(K$)<>0 then S=val(L$)/val(K$):L$=str$(S) else L$="error" goto [U] [7] call k,"7":wait [8] call k,"8":wait [9] call k,"9":wait [x] S=val(L$)*val(K$):goto [u] [4] call k,"4":wait [5] call k,"5":wait [6] call k,"6":wait [z] S=val(L$)-val(K$):goto [u] [1] call k,"1":wait [2] call k,"2":wait [3] call k,"3":wait [y] S=val(L$)+val(K$):goto [u] [0] call k,"0":wait [w] call k,".":wait [e] if K$=""then K$=L$ L$=K$:K$="":call u,L$:wait [q] close #1:end [u] L$=str$(S) [U] K$="":call u,L$:wait sub u D$ #1.t,D$ end sub sub k E$ K$=K$+E$:call u,K$ end sub
|
|
|
Post by Carl Gundel on Jan 29, 2020 20:17:56 GMT -5
If we didn't care about it being pretty we could get rid of this part of the first line. :WindowWidth=165:WindowHeight=200
|
|
|
Post by tsh73 on Jan 30, 2020 3:40:30 GMT -5
1174 removing /inlining everything Probably something should be done on interface - could it be done in graphicbox in less bytes?
nomainwin:global K$:WindowWidth=165:WindowHeight=200 textbox #1.t,5,1,142,25 button #1.c," C ",[c],UL,5,27 button #1.a,"+/-",[a],UL,40,27 button #1.r," % ",[r],UL,75,27 button #1.d," / ",[d],UL,110,27 button #1.7," 7 ",h,UL,5,53 button #1.8," 8 ",h,UL,40,53 button #1.9," 9 ",h,UL,75,53 button #1.x," x ",[x],UL,110,53 button #1.4," 4 ",h,UL,5,79 button #1.5," 5 ",h,UL,40,79 button #1.6," 6 ",h,UL,75,79 button #1.m," - ",[z],UL,110,79 button #1.1," 1 ",h,UL,5,105 button #1.2," 2 ",h,UL,40,105 button #1.3," 3 ",h,UL,75,105 button #1.p," + ",[y],UL,110,105 button #1.0," 0 ",h,UL,5,131 button #1..," . ",h,UL,40,131 button #1.e," Enter ",[e],UL,78,131 open""for window as #1:#1 "trapclose [q]":wait [c] K$="":#1.t,K$:wait [a]if K$="" then L$="";0-val(L$):#1.t,L$ else K$="";0-val(K$):#1.t,K$ wait [r] L$="";val(L$)*100:goto[U] [d]if val(K$)<>0 then S=val(L$)/val(K$):L$="";S else L$="error" goto[U] [x] S=val(L$)*val(K$):goto[u] [z] S=val(L$)-val(K$):goto[u] [y] S=val(L$)+val(K$):goto[u] [e]if K$=""then K$=L$ L$=K$:K$="":#1.t,L$:wait [q]close #1:end [u] L$="";S [U] K$="":#1.t,L$:wait sub h h$ K$=K$+right$(h$,1):#1.t,K$ end sub
|
|
|
Post by Carl Gundel on Jan 30, 2020 10:21:15 GMT -5
1174 removing /inlining everything Probably something should be done on interface - could it be done in graphicbox in less bytes? Yeah, I've been thinking the same thing about the graphicbox approach.
|
|
|
Post by David Drake on Jan 30, 2020 11:39:23 GMT -5
1174 removing /inlining everything Probably something should be done on interface - could it be done in graphicbox in less bytes? Yeah, I've been thinking the same thing about the graphicbox approach. Wow, there are some very creative programmers here. I'm not even sure what the line of code 'L$="";S' does. I've never seen this particular form before. Never thought about the graphicbox approach. I just assumed that it would result in more code. Need to give that a look.
|
|
|
Post by Rod on Jan 30, 2020 11:52:30 GMT -5
Well my first attempt building on Anatoly's code produces a larger file for graphicbox. 1290 bytes
global K$:WindowWidth=165:WindowHeight=230 open""for graphics_nf_nsb as #1 #1 "down ;trapclose [q]" #1 "place 10 60 ;\C +/- % /;\\7 8 9 x;\\4 5 6 -;\\1 2 3 +;\\0 . Enter" #1 "when leftButtonDown [p]" wait
[p] p$=str$(int((MouseX-10)/20))+str$(int((MouseY-30)/33)) select case p$ case "00" K$="":call u,K$ case "10" if K$="" then L$=str$(-1*val(L$)):call u,L$ if K$<>"" then K$=str$(-1*val(K$)):call u,K$ case "20" L$=str$(val(L$)*100):call u,L$:K$="" case "30" if val(K$)<>0 then S=val(L$)/val(K$):L$=str$(S):K$="" else K$="":L$="error" end if call u,L$ case "01" call k,"7" case "11" call k,"8" case "21" call k,"9" case "31" S=val(L$)*val(K$):L$=str$(S):K$="":call u,L$ case "02" call k,"4" case "12" call k,"5" case "22" call k,"6" case "32" S=val(L$)-val(K$):L$=str$(S):K$="":call u,L$ case "03" call k,"1" case "13" call k,"2" case "23" call k,"3" case "33" S=val(L$)+val(K$):L$=str$(S):K$="":call u,L$ case "04" call k,"0" case "14" call k,"." case "24" if K$=""then K$=L$ L$=K$:K$="":call u,L$ case "34" if K$=""then K$=L$ L$=K$:K$="":call u,L$ end select wait
[q] close #1:end
sub u D$ #1 "place 10 30 ;\";D$;" " end sub
sub k E$ K$=K$+E$:call u,K$ end sub
|
|
|
Post by tsh73 on Jan 30, 2020 12:06:04 GMT -5
Wow. I forger about line wrap in a graphic text printing.
EDIT after some thinking - I never knew in the first place.
BTW, semicolon between double backslash (linewrap) is unnecessary
|
|
|
Post by Chris Iverson on Jan 30, 2020 12:33:26 GMT -5
I'm not even sure what the line of code 'L$="";S' does. It's a shorthand form of 'L$ = str$(S)'. It converts a numeric variable into the string representation of that number. That example is taking advantage of special string concatenation rules in LB that let you combine string and numeric variables into a longer string without needing to explicitly convert the numeric variables. If you try to do: num = 12 L$ = "stuff" + num It fails with a type mismatch error, because + can only combine variables of the same type. It either adds together numbers, or concatenates strings. To use +, you'd have to do this: num = 12 L$ = "stuff" + str$(num) . To make it easier to output data of various types, LB has long allowed you to concatenate everything together into a single string regardless of type by using semicolons instead of plus signs to separate them. "";num will perform type conversion on num automatically, and will combine the empty string "" with the string "<numValue>", giving you just the string representation of numValue in a shorter number of characters than str$().
|
|
|
Post by tsh73 on Jan 30, 2020 12:51:27 GMT -5
Taking Rod's code and using "";num shortcut (and instr/mid as associative array), I got it fit in exactly 1000 bytes. I even added NOMAINWIN and FLASH (and preserved some empty lines!) I tried and it looks working (though clicking on a number above "buttons" gets some erroneous clicks - but initial Rod's code does the same).
nomainwin:global K$:WindowWidth=165:WindowHeight=230 open""for graphics_nf_nsb as #1 #1 "down;trapclose [q]" #1 "place 10 60;\C +/- % /\\7 8 9 x\\4 5 6 -\\1 2 3 +\\0 . Enter" #1 "flush" #1 "when leftButtonDown [p]" wait [p] p$="";int((MouseX-10)/20);int((MouseY-30)/33) p=instr(" 01 11 21 02 12 22 03 13 23 04 14 ",p$) if p then call k,mid$("7894561230.", p/3,1) else L=val(L$):K=val(K$) select case p$ case "00" K$="":call u,K$ case "10" if K$="" then L$="";0-L:call u,L$ else K$="";0-K:call u,K$ case "20" L$="";L*100:call u,L$:K$="" case "30" if val(K$)<>0 then S=L/K:L$="";S else L$="error" K$="" call u,L$ case "31" S=L*K:L$="";S:K$="":call u,L$ case "32" S=L-K:L$="";S:K$="":call u,L$ case "33" S=L+K:L$="";S:K$="":call u,L$ case "24","34" if K$=""then K$=L$ L$=K$:K$="":call u,L$ end select end if wait
[q]close #1:end
sub u D$ #1 "place 10 30 ;\";D$;space$(50) end sub
sub k E$ K$=K$+E$:call u,K$ end sub
|
|