5
\$\begingroup\$

Assume you're writing in one method, (or whatever you call them) with 3 inputs: the first string, a character that contains a +, - or * symbol, and the second string.

Example in Java:

public String strCalc(String str1, char sym, String str2) {
    //code...
}

What it should return:

str1 sym str2 ans
A     +  A   =  B
A     +  B   =  C
B     +  B   =  D
Z     +  A   =  AA
W     +  B   =  Y
A     -  A   =  ' ' (Space Character)
A     -  B   =  -A
A     -  C   =  -B
B     -  A   =  A
CA    -  A   =  BZ
A     *  A   =  A
B     *  B   =  D

Think of a one-indexed base 26. Then convert the numbers back to letters based on their position in the alphabet.

0 = ' ' (Space Character)
1 = A
2 = B
3 = C
4 = D
5 = E
6 = F
7 = G
8 = H
9 = I
10 = J
11 = K
and so on...

This is , so the shortest code in bytes not including the method declaration wins.

\$\endgroup\$
  • 1
    \$\begingroup\$ Are full programs allowed? \$\endgroup\$ – acrolith Oct 18 '16 at 17:24
  • \$\begingroup\$ This must be done within one method, if methods don't exist in the language you use, you may use full programs. \$\endgroup\$ – Kyza Oct 18 '16 at 17:28
  • 1
    \$\begingroup\$ I assume this is meant to just be math in one-based base 26, but could you clarify? \$\endgroup\$ – Geobits Oct 18 '16 at 17:35
  • \$\begingroup\$ I removed division because that would simply be too tedious. \$\endgroup\$ – Kyza Oct 18 '16 at 17:43
  • 1
    \$\begingroup\$ Must the method be able to handle zero (space-character) and negative inputs (such as "-AB")? \$\endgroup\$ – Martin Rosenau Oct 18 '16 at 20:38
2
\$\begingroup\$

Jelly, 64 63 bytes

Aḃ26ịØA
O_64»0ḅ26
e”-NḤ’×Ç
³Ç;“*×-_”y⁴¤;⁵ǤV
¢<0”-x;¢1Ŀ¤
¢⁶¢L¤?

Not a particularly clean solution; there are no 3 argument methods in Jelly, so this is a full program.

Accepts negative inputs like "-A", "- A", " -A", ... (note however "--A" is treated as "-A")
Accepts zero inputs like "", " ", " ", ...

TryItOnline

How?

Aḃ26ịØA           - Link 1, convert integer to absolute value string: i
A                 - absolute value of i
 ḃ26              - convert to bijective base 26 (a list of integers in [1,26])
    ị             - index into (1-based)
     ØA           - alphabet yield -> "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                  - (note: 0 will convert to an empty string here.)

O_64»0ḅ26         - Link 2, convert an input string to a positive integer: s
O                 - cast to ordinal (vectorises)
 _64              - subtract 64 from each (A->[1], B->[2], ..., AZ->[1,26], ...)
    »0            - maximum of that and zero ("-" and space become zeros; vectorises)
      ḅ26         - convert from base-26 to an integer (26 place values still work)

e”-NḤ’×Ç          - Link 3, convert an input string to an integer: s
 ”-               - literal '-'
e                 - exists in s?
   N              - negate
    Ḥ             - double
     ’            - increment (if "-" was in s we have -1, else we have 1)
      ×           - multiply by
       Ç          - call last link (2) as a monad

³Ç;“*×-_”y⁴¤;⁵ǤV - Link 4, evaluate the operation: niladic
³                 - first program input
 Ç                - call last link (3) as a monad (value of first input as an integer)
  ;               - concatenate with
           ¤      -     nilad followed by link(s) as a nilad
          ⁴       -     second program input
         y        -     map characters
   “*×-_”         -     literal "*×-_" - change "*" to "×" and "-" to "_"
            ;     - concatenate with
               ¤  -     nilad followed by link(s) as a nilad
             ⁵    -     third program input
              Ç   -     call last link (3) as a monad (value of 3rd input as integer)
                V - evaluate string as Jelly code (something like "-76×5" or "3_2")

¢<0”-x;¢1Ŀ¤       - Link 5, form output for non-zero results: niladic
¢                 - call the last link (4) as a nilad (integer result)
 <0               - less than zero?
   ”-             - literal '-'
     x            - repeat ('-' if negative '' if positive or zero)
      ;           - concatenate with
          ¤       -     nilad followed by link(s) as a nilad
       ¢          -     call the last link (4) as a nilad (integer result)
        1Ŀ        -     call the next link (1) as a monad (as absolute string)

¢⁶¢L¤?            - Main link: niladic (the program arguments expected however)
     ?            - ternary if
    ¤             -     nilad followed by link(s) as a nilad
  ¢               -     call the last link (5) as a nilad
   L              -     length
                  - True case (has length)
¢                 -     call the last link (5) as a nilad
                  - False case (no length)
 ⁶                - literal ' '
\$\endgroup\$
  • \$\begingroup\$ CA - A should be BZ -CA - A should be -BZ \$\endgroup\$ – Kyza Oct 18 '16 at 19:37
  • 1
    \$\begingroup\$ CA - A should be BZ \$\endgroup\$ – Kyza Oct 18 '16 at 19:38
  • \$\begingroup\$ Should all work now. \$\endgroup\$ – Jonathan Allan Oct 18 '16 at 21:46
1
\$\begingroup\$

Assembler x86 (32-bit) - 142 bytes

The 142 bytes are the compiled size (not the source code size, which is larger). Note that for assembler the size of the compiled code is not dependend on the compiler used but it should always be 142 bytes.

The calling convention is "_cdecl" so you can call the function from C:

const char *strCalc(const char *num1,
    char operation, const char *num2, char *bufferEnd);

The function accepts negative inputs (such as "-AB") and zero (" "). However malformed inputs might crash the program!

The last argument points to the LAST byte of a buffer used to store the sring because C does not support strings without pre-allocated buffers.

The function returns the pointer to the string (somewhere in the buffer). The function may be called the following way:

#include <stdio.h>

const char *strCalc(const char *num1, char operation, const char *num2, char *bufferEnd);

main(int argc,char **argv)
{
    char buf[21];
    puts(strCalc(argv[1],argv[2][0],argv[3],buf+20));
}

Here is the actual function (Linux users: Replace "_strCalc" by "strCalc"):

    .globl _strCalc
    .text
_strCalc:
    push %ebx
    push %esi
    push %edi
    mov 16(%esp), %esi
    call loadNum
    push %ebx
    mov 28(%esp), %esi
    call loadNum
    pop %eax
    # This assumes that the operation is ONLY +, * or -!
    cmpb $0x2B, 20(%esp)
    je isPlus
    jb isMultiply
    sub %ebx, %eax
    jmp calcDone
isPlus:
    add %ebx, %eax
    jmp calcDone
isMultiply:
    xor %edx, %edx
    imul %ebx
calcDone:
    push %eax
    mov 32(%esp), %edi
    std
    xor %al, %al
    stosb
    pop %eax
    call writeOut
    mov %al, (%edi)
    mov %edi, %eax
    inc %eax
    pop %edi
    pop %esi
    pop %ebx
    # Needed due to MSVCRT.DLL bug!
    cld
    ret

    # Write EAX to the buffer
    # EDI points to the last character to be
    # written (the terminating NUL has already been written)
    # Returns: EDI pointer to the first character!
writeOut:
    test %eax, %eax
    jnz notZero
    mov $0x20, %al
    stosb
    ret
notZero:
    jns notNegative
    neg %eax
    call writeOut
    mov $0x2D,%al
    stosb
    ret
notNegative:
    xor %edx, %edx
    dec %eax
    div %ecx
    xchg %al, %dl
    add $0x41, %al
    stosb
    xchg %al, %dl
    test %eax, %eax
    jnz notNegative
    xchg %al, %dl
    ret

    # Load number from string ESI points to to EBX
    # Destroys EAX, ECX, EDX
    # Allows negative and zero inputs!
    # Assumes syntactically correct numbers!
    # Sets ECX to 26 (needed later!)
loadNum:
    xor %ebx, %ebx
    xor %eax, %eax
    mov $26, %al
    mov %eax, %ecx
nextLoad:
    cld
    lodsb
    and $0xDF, %al
    jz endOfLoad
    sub $0x40, %al
    jc negativeInput
    xchg %eax, %ebx
    mul %ecx
    add %eax, %ebx
    jmp nextLoad
negativeInput:
    call loadNum
    neg %ebx
endOfLoad:
    ret
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.