UPC: Difference between revisions

4,838 bytes added ,  2 years ago
Added solution for Action!
(Added solution for Action!)
Line 185:
[7, 0, 6, 4, 6, 6, 7, 4, 3, 0, 3, 0]
[6, 5, 3, 4, 8, 3, 5, 4, 0, 4, 3, 5]
</pre>
 
=={{header|Action!}}==
<lang Action!>DEFINE PTR="CARD"
DEFINE RESOK="255"
DEFINE RESUPSIDEDOWN="254"
DEFINE RESINVALID="253"
DEFINE DIGITCOUNT="12"
DEFINE DIGITLEN="7"
 
PTR ARRAY ldigits(10),rdigits(10)
CHAR ARRAY marker="# #",midmarker=" # # "
 
PROC Init()
ldigits(0)=" ## #" ldigits(1)=" ## #"
ldigits(2)=" # ##" ldigits(3)=" #### #"
ldigits(4)=" # ##" ldigits(5)=" ## #"
ldigits(6)=" # ####" ldigits(7)=" ### ##"
ldigits(8)=" ## ###" ldigits(9)=" # ##"
rdigits(0)="### # " rdigits(1)="## ## "
rdigits(2)="## ## " rdigits(3)="# # "
rdigits(4)="# ### " rdigits(5)="# ### "
rdigits(6)="# # " rdigits(7)="# # "
rdigits(8)="# # " rdigits(9)="### # "
RETURN
 
BYTE FUNC DecodeMarker(CHAR ARRAY s BYTE POINTER pos CHAR ARRAY marker)
CHAR ARRAY tmp(6)
BYTE x
 
x=pos^+marker(0)
IF x>s(0) THEN
RETURN (RESINVALID)
ELSE
SCopyS(tmp,s,pos^,pos^+marker(0)-1)
pos^==+marker(0)
IF SCompare(tmp,marker)#0 THEN
RETURN (RESINVALID)
FI
FI
RETURN (RESOK)
 
BYTE FUNC DecodeDigit(CHAR ARRAY s BYTE POINTER pos PTR ARRAY digits)
CHAR ARRAY tmp(DIGITLEN+1)
BYTE i,x
 
x=pos^+DIGITLEN
IF x>s(0) THEN
RETURN (RESINVALID)
ELSE
SCopyS(tmp,s,pos^,pos^+DIGITLEN-1)
pos^==+DIGITLEN
FOR i=0 TO 9
DO
IF SCompare(tmp,digits(i))=0 THEN
RETURN (i)
FI
OD
FI
RETURN (RESINVALID)
 
BYTE FUNC Validation(BYTE ARRAY code)
BYTE ARRAY mult=[3 1 3 1 3 1 3 1 3 1 3 1]
BYTE i
INT sum
 
sum=0
FOR i=0 TO DIGITCOUNT-1
DO
sum==+code(i)*mult(i)
OD
IF sum MOD 10=0 THEN
RETURN (RESOK)
FI
RETURN (RESINVALID)
 
BYTE FUNC DecodeInternal(CHAR ARRAY s BYTE ARRAY code)
BYTE res,pos,i
 
pos=1
WHILE pos<=s(0) AND s(pos)=32
DO pos==+1 OD
 
res=DecodeMarker(s,@pos,marker)
IF res=RESINVALID THEN RETURN (res) FI
 
FOR i=0 TO 5
DO
res=DecodeDigit(s,@pos,ldigits)
IF res=RESINVALID THEN RETURN (res) FI
code(i)=res
OD
res=DecodeMarker(s,@pos,midmarker)
IF res=RESINVALID THEN RETURN (res) FI
 
FOR i=6 TO 11
DO
res=DecodeDigit(s,@pos,rdigits)
IF res=RESINVALID THEN RETURN (res) FI
code(i)=res
OD
 
res=DecodeMarker(s,@pos,marker)
IF res=RESINVALID THEN RETURN (res) FI
res=Validation(code)
RETURN (res)
 
PROC Reverse(CHAR ARRAY src,dst)
BYTE i,j
 
i=1 j=src(0) dst(0)=j
WHILE j>0
DO
dst(j)=src(i)
i==+1 j==-1
OD
RETURN
 
BYTE FUNC Decode(CHAR ARRAY s BYTE ARRAY code)
CHAR ARRAY tmp(256)
BYTE res
 
res=DecodeInternal(s,code)
IF res=RESOK THEN RETURN (res) FI
Reverse(s,tmp)
res=DecodeInternal(tmp,code)
IF res=RESINVALID THEN RETURN (res) FI
RETURN (RESUPSIDEDOWN)
 
PROC Test(BYTE id CHAR ARRAY s)
BYTE ARRAY code(DIGITCOUNT)
BYTE res,i
 
res=Decode(s,code)
IF id<10 THEN Put(32) FI
PrintF("%B: ",id)
IF res=RESINVALID THEN
PrintE("invalid")
ELSE
FOR i=0 TO DIGITCOUNT-1
DO
PrintB(code(i))
OD
IF res=RESUPSIDEDOWN THEN
PrintE(" valid (upside down)")
ELSE
PrintE(" valid")
FI
FI
RETURN
 
PROC Main()
PTR ARRAY codes(10)
BYTE i
Init()
codes(0)=" # # # ## # ## # ## ### ## ### ## #### # # # ## ## # # ## ## ### # ## ## ### # # # "
codes(1)=" # # # ## ## # #### # # ## # ## # ## # # # ### # ### ## ## ### # # ### ### # # # "
codes(2)=" # # # # # ### # # # # # # # # # # ## # ## # ## # ## # # #### ### ## # # "
codes(3)=" # # ## ## ## ## # # # # ### # ## ## # # # ## ## # ### ## ## # # #### ## # # # "
codes(4)=" # # ### ## # ## ## ### ## # ## # # ## # # ### # ## ## # # ### # ## ## # # # "
codes(5)=" # # # # ## ## # # # # ## ## # # # # # #### # ## # #### #### # # ## # #### # # "
codes(6)=" # # # ## ## # # ## ## # ### ## ## # # # # # # # # ### # # ### # # # # # "
codes(7)=" # # # # ## ## # # ## ## ### # # # # # ### ## ## ### ## ### ### ## # ## ### ## # # "
codes(8)=" # # ### ## ## # # #### # ## # #### # #### # # # # # ### # # ### # # # ### # # # "
codes(9)=" # # # #### ## # #### # # ## ## ### #### # # # # ### # ### ### # # ### # # # ### # # "
FOR i=0 TO 9
DO
Test(i+1,codes(i))
OD
RETURN</lang>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/UPC.png Screenshot from Atari 8-bit computer]
<pre>
1: 924773271019 valid
2: 403944441050 valid
3: 834999676706 valid (upside down)
4: 939825158811 valid (upside down)
5: invalid
6: 316313718717 valid (upside down)
7: 214575875608 valid
8: 818778841813 valid (upside down)
9: 706466743030 valid
10: 653483540435 valid
</pre>
 
Anonymous user