Lunar arithmetic
This page uses content from Wikipedia. The original article was at Lunar arithmetic. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |
Lunar arithmetic is a version of arithmetic in which the addition and multiplication on digits are defined as the max and min operations. Thus, in lunar arithmetic,
- and
The lunar arithmetic operations on nonnegative multidigit numbers are performed as in usual arithmetic as illustrated in the following examples. The world of lunar arithmetic is restricted to the set of nonnegative integers.
976 + 348 ---- 978 (adding digits column-wise)
976 × 348 ---- 876 (multiplying the digits of 976 by 8) 444 (multiplying the digits of 976 by 4) 333 (multiplying the digits of 976 by 3) ------ 34876 (adding digits column-wise)
A few important properties of lunar arithmetic
- The lunar addition and multiplication operations satisfy the Commutative and Associative property laws.
- The lunar multiplication distributes over the lunar addition.
- The digit 0 is the additive identity under lunar addition.
- The digit 9 is the multiplicative identity under lunar multiplication.
Note that lunar arithmetic can be done in any base. This task is restricted to base 10 only.
- Task
Implement lunar addition and lunar multiplication routines. Extra kudos for implementing them as operators.
Use those routines (operators) to perform the following:
- Lunar addition and lunar multiplication of the number groups: (976, 348), (23, 321), (232, 35), (123, 32192, 415, 8)
- Using lunar arithmetic, find the first twenty distinct even numbers. and . The even numbers are numbers of the form .
- Using lunar arithmetic, find the first twenty square numbers.
- Using lunar arithmetic, find the first twenty factorial numbers.
- Stretch
The lunar squares sequence is not monotonic. Squared values are not strictly increasing as the numbers grow larger.
- Find the first number whose lunar square is smaller than the previous.
- See also
- OEIS A087019 - Lunar squares
- OEIS A189788 - Base-10 lunar factorials
- Tropical algebra overloading
ALGOL 68
Assumes INT is large enough to hold the 20th lunar factorial - this is true for ALGOL 68 Genie version 3, but not version 2.
Algol 68 allows the definition of new operators, either symbolic or with alphabetic names. For symbolic operators 1 and 2 character names, possibly followed by := or =: are allowed.
However, monadic operator names cannot start with <. =, >, / or *, so although <* is OK as a dyadic operator, it isn't allowed as a monadic operator - which is why the monadic lunar multiplication operator defined here (to calculate the lunar product of the elements of an array) is called CX.
Algol 68n implementations tend not to do Unicode, so the lunar operators can't have a crescent in their names so-+> and <* are used here - that's not a relational operator, it's a crescent moon... : )
BEGIN # Lunar arithmetic #
INT max lunar digits = ENTIER log( max int ); # maximum number of digits #
# a lunar number can have #
# if stored in an INT #
[ 1 : max lunar digits + 1 ]INT lunar digits;
PRIO +> = 6, <* = 7; # same priorities as + and * #
OP +> = ( INT a, b )INT: # lunar addition of a and b #
IF a < 0 OR b < 0
THEN print( ( "Lunar numbers must be non-negative", newline ) );
stop
ELIF a = b
THEN a
ELSE INT v1 := a, v2 := b;
INT d pos := 0;
WHILE v1 > 0 OR v2 > 0 DO
INT d1 = v1 MOD 10, d2 = v2 MOD 10;
lunar digits[ d pos +:= 1 ] := IF d1 > d2 THEN d1 ELSE d2 FI;
v1 OVERAB 10;
v2 OVERAB 10
OD;
INT result := lunar digits[ d pos ];
WHILE ( d pos -:= 1 ) > 0 DO
result *:= 10 +:= lunar digits[ d pos ]
OD;
result
FI # +> # ;
PRIO +>:= = 1; # lunar add-and-assign, same priority as +:= #
OP +>:= = ( REF INT a, INT b )REF INT: a := a +> b;
OP <* = ( INT a, b )INT: # lunar multiplication of a and b #
IF a < 0 OR b < 0
THEN printf( ( "Lunar numbers must be non-negative", newline ) );
stop
ELIF a = 0 OR b = 0
THEN 0
ELSE INT v2 := b, multiplier := 1;
INT result := 0;
WHILE v2 > 0 DO
INT d2 = v2 MOD 10;
INT d pos := 0;
INT v1 := a;
WHILE v1 > 0 DO
INT d1 = v1 MOD 10;
lunar digits[ d pos +:= 1 ] := IF d1 < d2 THEN d1 ELSE d2 FI;
v1 OVERAB 10
OD;
INT p1 := lunar digits[ d pos ];
WHILE ( d pos -:= 1 ) > 0 DO
p1 *:= 10 +:= lunar digits[ d pos ]
OD;
result +>:= p1 * multiplier;
multiplier *:= 10;
v2 OVERAB 10
OD;
result
FI # <* # ;
PRIO <*:= = 1; # lunar multiply-and-assign, same priority as *:= #
OP <*:= = ( REF INT a, INT b )REF INT: a := a <* b;
OP +> = ( []INT a )INT: # lunar addition of the elements of a #
BEGIN
INT result := IF UPB a < LWB a THEN 0 ELSE a[ LWB a ] FI;
FOR a pos FROM LWB a + 1 TO UPB a DO
result +>:= a[ a pos ]
OD;
result
END # +> # ;
OP CX = ( []INT a )INT: # lunar multiplication of the elements of a #
BEGIN # unfortunately, <* isn't a valid unary operator name #
INT result := IF UPB a < LWB a THEN 0 ELSE a[ LWB a ] FI;
FOR a pos FROM LWB a + 1 TO UPB a DO
result <*:= a[ a pos ]
OD;
result
END # CX # ;
BEGIN # task #
[][]INT tests = ( ( 976, 348 ), ( 23, 321 ), ( 232, 35 ), ( 123, 32192, 415, 8 ) );
PROC show test = ( []INT v, STRING op name, INT result )VOID:
IF UPB v >= LWB v THEN
print( ( whole( v[ LWB v ], -8 ) ) );
FOR v pos FROM LWB v + 1 TO UPB v DO
print( ( " ", op name, " ", whole( v[ v pos ], 0 ) ) )
OD;
print( ( " = ", whole( result, 0 ), newline ) )
FI # show test # ;
print( ( "Lunar addition (+>):", newline ) );
FOR t pos FROM 1 LWB tests TO 1 UPB tests DO
show test( tests[ t pos ], "+>", +> tests[ t pos ] )
OD;
print( ( "Lunar multiplication (<*):", newline ) );
FOR t pos FROM 1 LWB tests TO 1 UPB tests DO
show test( tests[ t pos ], "<*", CX tests[ t pos ] )
OD;
BEGIN
print( ( "The first 20 distinct even lunar numbers:", newline, " " ) );
[ 0 : 1000 ]BOOL even; # assume they are all < 1001 #
FOR n FROM LWB even TO UPB even DO even[ n ] := FALSE OD;
FOR n FROM LWB even TO UPB even DO
IF INT n2 = n <* 2; n2 <= UPB even THEN even[ n <* 2 ] := TRUE FI
OD;
INT found := 0;
FOR n FROM LWB even WHILE found < 20 DO
IF even[ n ] THEN print( ( " ", whole( n, 0 ) ) ); found +:= 1 FI
OD;
print( ( newline ) )
END;
print( ( "The first 20 lunar squares:", newline, " " ) );
FOR n FROM 0 TO 19 DO print( ( " ", whole( n <* n, 0 ) ) ) OD;
print( ( newline ) );
BEGIN
INT f max = IF max lunar digits >= 18 THEN 20 ELIF max lunar digits >= 9 THEN 18 ELSE 9 FI;
print( ( "The first ", whole( f max, 0 ), " lunar factorials:", newline, " " ) );
INT lf := 1;
FOR n TO f max DO print( ( " ", whole( lf <*:= n, 0 ) ) ) OD;
print( ( newline ) )
END;
BEGIN
print( ( "First lunar square smaller than the previous: " ) );
INT prev square := 0;
INT this square := 1;
INT first n := 0;
FOR n FROM 2 WHILE first n = 0 DO
prev square := this square;
IF this square := n <* n;
this square < prev square
THEN first n := n
FI
OD;
print( ( whole( first n, 0 ), " squared = ", whole( this square, 0 ) ) );
print( ( ", previous = ", whole( prev square, 0 ), newline ) )
END
END
END
- Output:
Lunar addition (+>): 976 +> 348 = 978 23 +> 321 = 323 232 +> 35 = 235 123 +> 32192 +> 415 +> 8 = 32498 Lunar multiplication (<*): 976 <* 348 = 34876 23 <* 321 = 2321 232 <* 35 = 2332 123 <* 32192 <* 415 <* 8 = 123233232 The first 20 distinct even lunar numbers: 0 1 2 10 11 12 20 21 22 100 101 102 110 111 112 120 121 122 200 201 The first 20 lunar squares: 0 1 2 3 4 5 6 7 8 9 100 111 112 113 114 115 116 117 118 119 The first 18 lunar factorials: 1 1 1 1 1 1 1 1 1 10 110 1110 11110 111110 1111110 11111110 111111110 1111111110 First lunar square smaller than the previous: 1020 squared = 1010200, previous = 1011119
BASIC
FreeBASIC
Function LunarAdd(a As String, b As String) As String
Dim result As String
Dim maxLen As Integer = Iif(Len(a) > Len(b), Len(a), Len(b))
a = String(maxLen - Len(a), "0") & a
b = String(maxLen - Len(b), "0") & b
For i As Integer = 1 To maxLen
Dim digit As Integer = Iif(Val(Mid(a, i, 1)) > Val(Mid(b, i, 1)), Val(Mid(a, i, 1)), Val(Mid(b, i, 1)))
result &= Str(digit)
Next
Return Ltrim(result)
End Function
Function LunarMultiply(a As String, b As String = "9") As String
If a = "0" Or b = "0" Then Return "0"
Dim result As String = "0"
For i As Integer = Len(b) To 1 Step -1
Dim tmp As String = ""
Dim bDigit As Integer = Val(Mid(b, i, 1))
For j As Integer = 1 To Len(a)
Dim aDigit As Integer = Val(Mid(a, j, 1))
tmp &= Str(Iif(aDigit < bDigit, aDigit, bDigit))
Next
tmp &= String(Len(b) - i, "0")
result = LunarAdd(result, Ltrim(tmp))
Next
Return result
End Function
Function isUnique(value As String, arr() As String, cnt As Integer) As Boolean
For i As Integer = 0 To cnt - 1
If arr(i) = value Then Return False
Next
Return True
End Function
Sub main()
Print " Lunar add: 976 + 348 = "; LunarAdd("976", "348")
Print "Lunar multiply: 976 x 348 = "; LunarMultiply("976", "348")
Print
Print " Lunar add: 23 + 321 = "; LunarAdd("23", "321")
Print "Lunar multiply: 23 x 321 = "; LunarMultiply("23", "321")
Print
Print " Lunar add: 232 + 35 = "; LunarAdd("232", "35")
Print "Lunar multiply: 232 x 35 = "; LunarMultiply("232", "35")
Print
Print " Lunar add: 123 + 32192 + 415 + 8 = "; LunarAdd(LunarAdd(LunarAdd("123", "32192"), "415"), "8")
Print "Lunar multiply: 123 x 32192 x 415 x 8 = "; LunarMultiply(LunarMultiply(LunarMultiply("123", "32192"), "415"), "8")
Print
Print "First 20 distinct lunar even numbers:"
Dim evenNums(1000) As String
Dim cnt As Integer = 0
Dim n As Integer = 0
Do While cnt < 20
Dim result As String = LunarMultiply(Str(n), "2")
If isUnique(result, evenNums(), cnt) Then
evenNums(cnt) = result
Print result; " ";
cnt += 1
End If
n += 1
Loop
Print !"\n\nFirst 20 lunar square numbers:"
For i As Integer = 0 To 19
Print LunarMultiply(Str(i), Str(i)); " ";
Next
Print !"\n\nFirst 20 lunar factorial numbers:"
Dim factorial As String = "1"
Print "1";
For i As Integer = 1 To 19
factorial = LunarMultiply(factorial, Str(i + 1))
Print " "; factorial;
Next
Dim prevSquare As String = ""
Dim currSquare As String
For i As LongInt = 1 To 1200
currSquare = lunarMultiply(Str(i), Str(i))
If prevSquare <> "" AndAlso Val(currSquare) < Val(prevSquare) Then
Print !"\n\nFirst number whose lunar square is smaller than the previous:"; i
Exit For
End If
prevSquare = currSquare
Next
End Sub
main()
Sleep
- Output:
Lunar add: 976 + 348 = 978 Lunar multiply: 976 x 348 = 34876 Lunar add: 23 + 321 = 323 Lunar multiply: 23 x 321 = 2321 Lunar add: 232 + 35 = 235 Lunar multiply: 232 x 35 = 2332 Lunar add: 123 + 32192 + 415 + 8 = 32498 Lunar multiply: 123 x 32192 x 415 x 8 = 123233232 First 20 distinct even lunar numbers: 0 1 2 10 11 12 20 21 22 100 101 102 110 111 112 120 121 122 200 201 First 20 square lunar numbers: 0 1 2 3 4 5 6 7 8 9 100 111 112 113 114 115 116 117 118 119 First 20 factorial lunar numbers: 1 1 1 1 1 1 1 1 1 10 110 1110 11110 111110 1111110 11111110 111111110 1111111110 11111111110 111111111100 First number whose lunar square is smaller than the previous: 1020
Gambas
Private evenNums As New String[]
Public Function LunarAdd(a As String, b As String) As String
Dim result As String
Dim maxLen As Integer = IIf(Len(a) > Len(b), Len(a), Len(b))
Dim i As Integer
a = String$(maxLen - Len(a), "0") & a
b = String$(maxLen - Len(b), "0") & b
For i = 1 To maxLen
result &= IIf(Val(Mid$(a, i, 1)) > Val(Mid$(b, i, 1)), Mid$(a, i, 1), Mid$(b, i, 1))
Next
Return LTrim(result)
End
Public Function LunarMultiply(a As String, b As String) As String
If a = "0" Or b = "0" Then Return "0"
Dim i As Integer, j As Integer
Dim result As String = "0"
For i = Len(b) To 1 Step -1
Dim tmp As String = ""
Dim bDigit As Integer = Val(Mid$(b, i, 1))
For j = 1 To Len(a)
Dim aDigit As Integer = Val(Mid$(a, j, 1))
tmp &= Min(aDigit, bDigit)
Next
tmp &= String$(Len(b) - i, "0")
result = LunarAdd(result, tmp)
Next
Return result
End
Public Function isUnique(value As String, arr As String[], cnt As Integer) As Boolean
For i As Integer = 0 To cnt - 1
If arr[i] = value Then Return False
Next
Return True
End
Public Sub main()
Print " Lunar add: 976 + 348 == "; LunarAdd("976", "348")
Print "Lunar multiply: 976 × 348 == "; LunarMultiply("976", "348")
Print
Print " Lunar add: 23 + 321 = "; LunarAdd("23", "321")
Print "Lunar multiply: 23 x 321 = "; LunarMultiply("23", "321")
Print
Print " Lunar add: 232 + 35 = "; LunarAdd("232", "35")
Print "Lunar multiply: 232 x 35 = "; LunarMultiply("232", "35")
Print
Print " Lunar add: 123 + 32192 + 415 + 8 = "; LunarAdd(LunarAdd(LunarAdd("123", "32192"), "415"), "8")
Print "Lunar multiply: 123 x 32192 x 415 x 8 = "; LunarMultiply(LunarMultiply(LunarMultiply("123", "32192"), "415"), "8")
Print
Print "First 20 distinct lunar even numbers:"
' Dim evenNums(1000) As String
Dim cnt As Integer = 0
Dim n As Integer = 0
Do While cnt < 20
Dim result As String = LunarMultiply(Str(n), "2")
If isUnique(result, evenNums, cnt) Then
evenNums.Add(result)
Print result; " ";
cnt += 1
End If
n += 1
Loop
Print "\n\nFirst 20 lunar square numbers:"
For i As Integer = 0 To 19
Print LunarMultiply(Str(i), Str(i)); " ";
Next
Print "\n\nFirst 20 lunar factorial numbers:"
Dim factorial As String = "1"
Print "1";
For i As Integer = 1 To 19
factorial = LunarMultiply(factorial, Str(i + 1))
Print " "; factorial;
Next
n = 1
Dim prevSquare, currSquare As String
prevSquare = LunarMultiply(Str(n), Str(n))
Do
currSquare = LunarMultiply(Str(n + 1), Str(n + 1))
If prevSquare <> "" And Val(currSquare) < Val(prevSquare) Then
Print "\n\nFirst number whose lunar square is smaller than the previous: "; n + 1
Break
Endif
prevSquare = currSquare
n += 1
Loop
End
- Output:
Same as FreeBASIC entry.
PureBasic
Procedure Max(a, b)
If a > b
ProcedureReturn a
EndIf
ProcedureReturn b
EndProcedure
Procedure Min(a, b)
If a < b
ProcedureReturn a
EndIf
ProcedureReturn b
EndProcedure
Procedure.s LunarAdd(a.s, b.s)
maxLen = Max(Len(a), Len(b))
a = RSet(a, maxLen, "0")
b = RSet(b, maxLen, "0")
result.s = ""
For i = 1 To maxLen
digit1 = Val(Mid(a, i, 1))
digit2 = Val(Mid(b, i, 1))
result + Str(Max(digit1, digit2))
Next
ProcedureReturn Trim(result)
EndProcedure
Procedure.s LunarMultiply(a.s, b.s)
If a = "0" Or b = "0"
ProcedureReturn "0"
EndIf
result.s = "0"
For i = Len(b) To 1 Step -1
tmp.s = ""
bDigit = Val(Mid(b, i, 1))
For j = 1 To Len(a)
aDigit = Val(Mid(a, j, 1))
tmp + Str(Min(aDigit, bDigit))
Next
tmp + RSet("", Len(b) - i, "0")
result = LunarAdd(result, tmp)
Next
ProcedureReturn result
EndProcedure
Procedure isUnique(value.s, Array arr.s(1), cnt)
For i = 0 To cnt - 1
If arr(i) = value
ProcedureReturn #False
EndIf
Next
ProcedureReturn #True
EndProcedure
OpenConsole()
Define result.s
; First test set
PrintN(" Lunar add: 976 + 348 = " + LunarAdd("976", "348"))
PrintN("Lunar multiply: 976 × 348 = " + LunarMultiply("976", "348") + #CRLF$)
; Second test set
PrintN(" Lunar add: 23 + 321 = " + LunarAdd("23", "321"))
PrintN("Lunar multiply: 23 × 321 = " + LunarMultiply("23", "321") + #CRLF$)
; Third test set
PrintN(" Lunar add: 232 + 35 = " + LunarAdd("232", "35"))
PrintN("Lunar multiply: 232 × 35 = " + LunarMultiply("232", "35") + #CRLF$)
; Fourth test set
result = LunarAdd(LunarAdd(LunarAdd("123", "32192"), "415"), "8")
PrintN(" Lunar add: 123 + 32192 + 415 + 8 = " + result)
result = LunarMultiply(LunarMultiply(LunarMultiply("123", "32192"), "415"), "8")
PrintN("Lunar multiply: 123 × 32192 × 415 × 8 = " + result + #CRLF$)
; Lunar even numbers
PrintN("First 20 distinct lunar even numbers:")
Dim evenNums.s(1000)
cnt = 0
n = 0
While cnt < 20
result.s = LunarMultiply(Str(n), "2")
If isUnique(result, evenNums(), cnt)
evenNums(cnt) = result
Print(result + " ")
cnt + 1
EndIf
n + 1
Wend
; Lunar squares
PrintN(#CRLF$ + #CRLF$ + "First 20 lunar square numbers:")
For i = 0 To 19
Print(LunarMultiply(Str(i), Str(i)) + " ")
Next
; Lunar factorials
PrintN(#CRLF$ + #CRLF$ + "First 20 lunar factorial numbers:")
factorial.s = "1"
Print("1")
For i = 1 To 19
factorial = LunarMultiply(factorial, Str(i + 1))
Print(" " + factorial)
Next
n = 1
prevSquare.s = LunarMultiply(Str(n), Str(n))
Repeat
;prevSquare.s = LunarMultiply(Str(n), Str(n))
currSquare.s = LunarMultiply(Str(n + 1), Str(n + 1))
If prevSquare <> "" And Val(currSquare) < Val(prevSquare)
PrintN(#CRLF$ + #CRLF$ + "First number whose lunar square is smaller than the previous: " + Str(n + 1))
Break
EndIf
prevSquare = currSquare
n + 1
ForEver
PrintN(#CRLF$ + "Press ENTER to exit"): Input()
- Output:
Similar to FreeBASIC entry.
QBasic
DECLARE FUNCTION PadLeft$ (s AS STRING, length AS INTEGER)
DECLARE FUNCTION LunarAdd$ (a AS STRING, b AS STRING)
DECLARE FUNCTION LunarMultiply$ (a AS STRING, b AS STRING)
DECLARE FUNCTION isUnique% (value AS STRING, arr$(), cnt AS INTEGER)
PRINT " Lunar add: 976 + 348 = "; LunarAdd$("976", "348")
PRINT "Lunar multiply: 976 x 348 = "; LunarMultiply$("976", "348")
PRINT
PRINT " Lunar add: 23 + 321 = "; LunarAdd$("23", "321")
PRINT "Lunar multiply: 23 x 321 = "; LunarMultiply$("23", "321")
PRINT
PRINT " Lunar add: 232 + 35 = "; LunarAdd$("232", "35")
PRINT "Lunar multiply: 232 x 35 = "; LunarMultiply$("232", "35")
PRINT
PRINT " Lunar add: 123 + 32192 + 415 + 8 = "; LunarAdd$(LunarAdd$(LunarAdd$("123", "32192"), "415"), "8")
PRINT "Lunar multiply: 123 x 32192 x 415 x 8 = "; LunarMultiply$(LunarMultiply$(LunarMultiply$("123", "32192"), "415"), "8")
PRINT
PRINT "First 20 distinct lunar even numbers:"
DIM evenNums$(1000)
DIM cnt AS INTEGER, n AS INTEGER, i AS INTEGER
DO WHILE cnt < 20
DIM result AS STRING
result = LunarMultiply$(STR$(n), "2")
IF isUnique%(result, evenNums$(), cnt) THEN
evenNums$(cnt) = result
PRINT result; " ";
cnt = cnt + 1
END IF
n = n + 1
LOOP
PRINT
PRINT
PRINT "First 20 lunar square numbers:"
FOR i = 0 TO 19
PRINT LunarMultiply$(STR$(i), STR$(i)); " ";
NEXT i
PRINT
PRINT
PRINT "First 20 lunar factorial numbers:"
DIM factorial AS STRING
factorial = "1"
PRINT factorial;
FOR i = 2 TO 20
factorial = LunarMultiply$(factorial, STR$(i))
PRINT " "; factorial;
NEXT i
PRINT
PRINT
DIM prevSquare AS STRING, currSquare AS STRING
DIM j AS LONG
j = 1
DO
currSquare = LunarMultiply$(STR$(j), STR$(j))
IF prevSquare <> "" AND VAL(currSquare) < VAL(prevSquare) THEN
PRINT "First number whose lunar square is smaller than the previous:"; j
EXIT DO
END IF
prevSquare = currSquare
j = j + 1
LOOP
END
FUNCTION isUnique% (value AS STRING, arr$(), cnt AS INTEGER)
DIM i AS INTEGER
FOR i = 0 TO cnt - 1
IF arr$(i) = value THEN
isUnique% = 0
EXIT FUNCTION
END IF
NEXT i
isUnique% = -1
END FUNCTION
FUNCTION LunarAdd$ (a AS STRING, b AS STRING)
DIM result AS STRING
DIM maxLen AS INTEGER, i AS INTEGER
DIM digitA AS INTEGER, digitB AS INTEGER, digit AS INTEGER
IF LEN(a) > LEN(b) THEN maxLen = LEN(a) ELSE maxLen = LEN(b)
a = PadLeft$(a, maxLen)
b = PadLeft$(b, maxLen)
FOR i = 1 TO maxLen
digitA = VAL(MID$(a, i, 1))
digitB = VAL(MID$(b, i, 1))
IF digitA > digitB THEN digit = digitA ELSE digit = digitB
result = result + CHR$(ASC("0") + digit)
NEXT i
WHILE LEFT$(result, 1) = "0" AND LEN(result) > 1
result = RIGHT$(result, LEN(result) - 1)
WEND
LunarAdd$ = result
END FUNCTION
FUNCTION LunarMultiply$ (a AS STRING, b AS STRING)
IF a = "0" OR b = "0" THEN
LunarMultiply$ = "0"
EXIT FUNCTION
END IF
DIM result AS STRING, tmp AS STRING
result = "0"
DIM i AS INTEGER, j AS INTEGER
DIM bDigit AS INTEGER, aDigit AS INTEGER
FOR i = LEN(b) TO 1 STEP -1
tmp = ""
bDigit = VAL(MID$(b, i, 1))
FOR j = 1 TO LEN(a)
aDigit = VAL(MID$(a, j, 1))
IF aDigit < bDigit THEN
tmp = tmp + CHR$(ASC("0") + aDigit)
ELSE
tmp = tmp + CHR$(ASC("0") + bDigit)
END IF
NEXT j
tmp = tmp + STRING$(LEN(b) - i, "0")
result = LunarAdd$(result, tmp)
NEXT i
WHILE LEFT$(result, 1) = "0" AND LEN(result) > 1
result = RIGHT$(result, LEN(result) - 1)
WEND
LunarMultiply$ = result
END FUNCTION
FUNCTION PadLeft$ (s AS STRING, length AS INTEGER)
IF LEN(s) >= length THEN
PadLeft$ = s
ELSE
PadLeft$ = STRING$(length - LEN(s), "0") + s
END IF
END FUNCTION
- Output:
Same as FreeBASIC entry.
QB64
The QBasic solution works without any changes.
EasyLang
func luadd a b .
e = 1
while a > 0 or b > 0
d = higher (a mod 10) (b mod 10)
a = a div 10
b = b div 10
r += d * e
e *= 10
.
return r
.
func lumul a0 b .
e0 = 1
while b > 0
e = e0
r = 0
a = a0
while a > 0
d = lower (a mod 10) (b mod 10)
a = a div 10
r += d * e
e *= 10
.
s = luadd s r
b = b div 10
e0 *= 10
.
return s
.
tests[][] = [ [ 976 348 ] [ 23 321 ] [ 232 35 ] [ 123 32192 415 8 ] ]
for i to len tests[][]
s = 0
p = 9
for h in tests[i][]
s = luadd s h
p = lumul p h
.
print "🌙+ " & tests[i][] & " -> " & s
print "🌙* " & tests[i][] & " -> " & p
print ""
.
print "First 20 distinct 🌙 even numbers:"
n = 1
while len nums[] < 20
r = lumul n 2
h = -1
for h in nums[]
if h = r : break 1
.
if h = -1 : nums[] &= r
n += 1
.
for h in nums[] : write h & " "
print ""
print ""
print "First 20 🌙 square numbers:"
for i to 20
write lumul i i & " "
.
print ""
print ""
print "First 20 🌙 factorial numbers:"
fac = 1
for i to 20
fac = lumul fac i
write fac & " "
.
print ""
print ""
h = 0
i = 1
repeat
h = lumul i i
until h < hp
i += 1
hp = h
.
print "First number whose 🌙 square is smaller than the previous: " & i
- Output:
🌙+ [ 976 348 ] -> 978 🌙* [ 976 348 ] -> 34876 🌙+ [ 23 321 ] -> 323 🌙* [ 23 321 ] -> 2321 🌙+ [ 232 35 ] -> 235 🌙* [ 232 35 ] -> 2332 🌙+ [ 123 32192 415 8 ] -> 32498 🌙* [ 123 32192 415 8 ] -> 123233232 First 20 distinct 🌙 even numbers: 1 2 10 11 12 20 21 22 100 101 102 110 111 112 120 121 122 200 201 202 First 20 🌙 square numbers: 1 2 3 4 5 6 7 8 9 100 111 112 113 114 115 116 117 118 119 200 First 20 🌙 factorial numbers: 1 1 1 1 1 1 1 1 1 10 110 1110 11110 111110 1111110 11111110 111111110 1111111110 11111111110 111111111100 First number whose 🌙 square is smaller than the previous: 1020
Python
#!/usr/bin/python3
def lunar_add(a, b='0'):
a, b = str(a), str(b)
max_len = max(len(a), len(b))
a = '0' * (max_len - len(a)) + a
b = '0' * (max_len - len(b)) + b
return ''.join(str(max(int(x), int(y))) for x, y in zip(a, b))
def lunar_multiply(a, b='9'):
if a == '0' or b == '0':
return '0'
a, b = str(a), str(b)
result = '0'
for i, digit in enumerate(reversed(b)):
temp = ''.join(str(min(int(x), int(digit))) for x in a)
temp += '0' * i
result = lunar_add(result, temp)
return result
def lunar_factorial(n):
if n <= 1:
return '1'
result = '1'
for i in range(2, n + 1):
result = lunar_multiply(result, str(i))
return result
def main():
# Test cases
test_cases = [(976, 348), (23, 321), (232, 35), (123, 32192, 415, 8)]
for case in test_cases:
# Lunar addition
add_expr = ' 🌙+ '.join(str(x) for x in case)
add_result = reduce(lunar_add, map(str, case))
print(f" Lunar add: {add_expr} == {add_result}")
# Lunar multiplication
mult_expr = ' 🌙× '.join(str(x) for x in case)
mult_result = reduce(lunar_multiply, map(str, case))
print(f"Lunar multiply: {mult_expr} == {mult_result}")
print()
# First 20 distinct lunar even numbers
even_nums = []
n = 0
while len(even_nums) < 20:
result = lunar_multiply(str(n), '2')
if result not in even_nums:
even_nums.append(result)
n += 1
print("First 20 distinct lunar even numbers:")
print(' '.join(even_nums))
print()
# First 20 lunar square numbers
squares = [lunar_multiply(str(i), str(i)) for i in range(20)]
print("First 20 lunar square numbers:")
print(' '.join(squares))
print()
# First 20 lunar factorial numbers
factorials = [lunar_factorial(i) for i in range(20)]
print("First 20 lunar factorial numbers:")
print(' '.join(factorials))
print()
# First number whose lunar square is smaller than previous
n = 1019 # We can start closer to the known solution
while True:
curr_square = lunar_multiply(str(n), str(n))
next_square = lunar_multiply(str(n + 1), str(n + 1))
if curr_square > next_square:
print(f"First number whose lunar square is smaller than the previous: {n + 1}")
break
n += 1
if __name__ == '__main__':
from functools import reduce
main()
- Output:
Lunar add: 976 🌙+ 348 == 978 Lunar multiply: 976 🌙× 348 == 34876 Lunar add: 23 🌙+ 321 == 323 Lunar multiply: 23 🌙× 321 == 2321 Lunar add: 232 🌙+ 35 == 235 Lunar multiply: 232 🌙× 35 == 2332 Lunar add: 123 🌙+ 32192 🌙+ 415 🌙+ 8 == 32498 Lunar multiply: 123 🌙× 32192 🌙× 415 🌙× 8 == 123233232 First 20 distinct lunar even numbers: 0 1 2 10 11 12 20 21 22 100 101 102 110 111 112 120 121 122 200 201 First 20 lunar square numbers: 0 1 2 3 4 5 6 7 8 9 100 111 112 113 114 115 116 117 118 119 First 20 lunar factorial numbers: 1 1 1 1 1 1 1 1 1 1 10 110 1110 11110 111110 1111110 11111110 111111110 1111111110 11111111110 First number whose lunar square is smaller than the previous: 1020
Raku
That's not a banana. That's a crescent moon.
# The operators
sub infix:<🌙+> ($a, $b = 0) { # addition
+([Zmax] ('0'x$b.chars~$a).comb,('0'x$a.chars~$b).comb).join;
}
sub infix:<🌙×> ($a, $b = 9) { # multiplication
[🌙+] $b.flip.comb.kv.map: -> $k,$v {$a.comb.map(* min $v).join ~ '0'x$k}
}
# The task
for (976, 348), (23, 321), (232, 35), (123, 32192, 415, 8) {
say ' Lunar add: ' ~ (.join: ' 🌙+ ') ~ ' == ' ~ (.join: ' 🌙+ ').EVAL;
say 'Lunar multiply: ' ~ (.join: ' 🌙× ') ~ ' == ' ~ (.join: ' 🌙× ').EVAL;
say '';
}
say "First 20 distinct lunar even numbers:\n" ~ (^Inf).map(* 🌙× 2).unique[^20];
say "\nFirst 20 lunar square numbers:\n" ~ (my @squares = (^Inf).map:{$_ 🌙× $_})[^20];
say "\nFirst 20 lunar factorial numbers:\n" ~ (1..*).map({[🌙×] 1..$_})[^20];
# Stretch
say "\nFirst number whose lunar square is smaller than the previous: " ~
(1..Inf).first: {@squares[$_ - 1] > @squares[$_]};
- Output:
Lunar add: 976 🌙+ 348 == 978 Lunar multiply: 976 🌙× 348 == 34876 Lunar add: 23 🌙+ 321 == 323 Lunar multiply: 23 🌙× 321 == 2321 Lunar add: 232 🌙+ 35 == 235 Lunar multiply: 232 🌙× 35 == 2332 Lunar add: 123 🌙+ 32192 🌙+ 415 🌙+ 8 == 32498 Lunar multiply: 123 🌙× 32192 🌙× 415 🌙× 8 == 123233232 First 20 distinct lunar even numbers: 0 1 2 10 11 12 20 21 22 100 101 102 110 111 112 120 121 122 200 201 First 20 lunar square numbers: 0 1 2 3 4 5 6 7 8 9 100 111 112 113 114 115 116 117 118 119 First 20 lunar factorial numbers: 1 1 1 1 1 1 1 1 1 10 110 1110 11110 111110 1111110 11111110 111111110 1111111110 11111111110 111111111100 First number whose lunar square is smaller than the previous: 1020
Uiua
Lunar! ← ⍜∩(⇌-@0°⋕)^0 # binary lunar op
☾ ← Lunar!⬚0↥ # add
☽ ← Lunar!(/(☾˜⊂0)⊞↧) # multiply
{976_348 23_321 232_35 [123 32192 415 8]}
∵◇(&p $"_ sum = _, product = _"⟜⊃/☾/☽)
&p "\nFirst 20 distinct even:"
&p ⇌◴⍢(⊂☽2⊸⧻|<20⧻◴)[]
&p "\nFirst 20 squares:"
&p ∵☽.⇡20
&p "\nFirst 20 factorials:"
&p ≡(/☽+1⇡)↘1⇡21
&p "\nFirst square smaller than previous:"
&p ⊙◌⍢∩+₁(<∩(☽.))1 0
- Output:
[976 348] sum = 978, product = 34876 [23 321] sum = 323, product = 2321 [232 35] sum = 235, product = 2332 [123 32192 415 8] sum = 32498, product = 123233232 First 20 distinct even: [0 1 2 10 11 12 20 21 22 100 101 102 110 111 112 120 121 122 200 201] First 20 squares: [0 1 2 3 4 5 6 7 8 9 100 111 112 113 114 115 116 117 118 119] First 20 factorials: [1 1 1 1 1 1 1 1 1 10 110 1110 11110 111110 1111110 11111110 111111110 1111111110 11111111110 111111111100] First square smaller than previous: 1020
Wren
Whilst we can override the existing '+' and '*' operators by wrapping non-negative integers in a new Lunar class, we can't introduce new ones.
import "./math" for Math, Int
var MOON = "🌙"
class Lunar {
static zero { Lunar.of(0) }
static one { Lunar.of(1) }
static nine { Lunar.of(9) }
construct of(n) {
if (!((n is Num) && n.isInteger && n >= 0)) {
Fiber.abort("Argument must be a non-negative integer.")
}
_n = n
}
n { _n }
getOps_(other) {
if (!(other is Lunar)) other = Lunar.of(other)
var op1 = Int.digits(_n)
var op2 = Int.digits(other.n)
var c1 = op1.count
var c2 = op2.count
if (c1 < c2) {
op1 = [0] * (c2 - c1) + op1
} else if (c2 < c1) {
op2 = [0] * (c1 - c2) + op2
}
return [op1, op2]
}
+(other) {
var ops = getOps_(other)
var res = (0...ops[0].count).map { |i| Math.max(ops[0][i], ops[1][i]) }.join("")
return Lunar.of(Num.fromString(res))
}
*(other) {
var ops = getOps_(other)
var count = ops[0].count
var lunars = List.filled(count, null)
var zeros = ""
for (i in count-1..0) {
var num = (0...count).map { |j| Math.min(ops[0][i], ops[1][j]) }.join("")
if (i < count - 1) zeros = zeros + "0"
lunars[count-1-i] = Lunar.of(Num.fromString(num + zeros))
}
return lunars.reduce { |acc, x| acc + x }
}
==(other) { _n == other.n }
<(other) { _n < other.n }
toString { _n.toString }
}
var tests = [ [976, 348], [23, 321], [232, 35], [123, 32192, 415, 8] ]
for (test in tests) {
var sum = test.reduce(Lunar.zero) { |acc, x| acc + x }
var prod = test.reduce(Lunar.nine) { |acc, x| acc * x }
System.print("Lunar add: %(test.join(" " + MOON + "+ ")) = %(sum)")
System.print("Lunar mul: %(test.join(" " + MOON + "× ")) = %(prod)\n")
}
System.print("First 20 distinct even lunar numbers:")
var i = 0
var evens = []
while (evens.count < 20) {
var even = Lunar.of(i) * 2
var isDistinct = true
for (j in evens) {
if (even == j) {
isDistinct = false
break
}
}
if (isDistinct) evens.add(even)
i = i + 1
}
System.print(evens.join(" "))
System.print("\nFirst 20 square lunar numbers:")
System.print((0...20).map { |i| Lunar.of(i) * i }.join(" "))
System.print("\nFirst 20 factorial lunar numbers:")
var fact = Lunar.one
for (i in 1..20) {
fact = fact * i
System.write("%(fact) ")
}
System.write("\n\nFirst number whose lunar square is smaller than the previous: ")
var prev = Lunar.zero
i = 1
while (true) {
var curr = Lunar.of(i) * i
if (curr < prev) {
System.print(i)
break
}
prev = curr
i = i + 1
}
- Output:
Lunar add: 976 🌙+ 348 = 978 Lunar mul: 976 🌙× 348 = 34876 Lunar add: 23 🌙+ 321 = 323 Lunar mul: 23 🌙× 321 = 2321 Lunar add: 232 🌙+ 35 = 235 Lunar mul: 232 🌙× 35 = 2332 Lunar add: 123 🌙+ 32192 🌙+ 415 🌙+ 8 = 32498 Lunar mul: 123 🌙× 32192 🌙× 415 🌙× 8 = 123233232 First 20 distinct even lunar numbers: 0 1 2 10 11 12 20 21 22 100 101 102 110 111 112 120 121 122 200 201 First 20 square lunar numbers: 0 1 2 3 4 5 6 7 8 9 100 111 112 113 114 115 116 117 118 119 First 20 factorial lunar numbers: 1 1 1 1 1 1 1 1 1 10 110 1110 11110 111110 1111110 11111110 111111110 1111111110 11111111110 111111111100 First number whose lunar square is smaller than the previous: 1020