12
\$\begingroup\$

Your function must accept two strings and return new string where are UTF-16 code of all symbols is the sum of UTF-16 codes of inputs symbols

  • If the resulting sum is greater than 65535 (maximum UTF-16 codepoint), take the sum modulo 65536

  • If there are more symbols in one string then sum with zero, codes of symbols which doesn't have pairs

For example:

  • 'a' + 'b' = a(97) + b(98) = 97 + 98 = 195 => 'Ã'
  • 'A' + 'B' = A(65) + B(66) = 65 + 66 = 131 => '\u0083' (No Break Here)
  • 'Aa' + 'BbC' = [A(65) + B(66)][a(97) + b(98)][(0) + C(67)] => '\u0083ÃC' - \u0083 will not be displayed but it must be here so the length of result string must be 3 not 2

Test cases:

'a', 'b' --> 'Ã'

'A', 'B' --> '\u0083'

'Aa', 'BbC' --> '\u0083ÃC'

'耀', '耀' --> '\u0000' (Null character)

'Программирование', 'Programming' --> 'ѯҲҭҚҲґҩҩҡҮҥвание'

Ungolfed version (check in real time):

const updateResult = () => {
  const string_1 = input1.value;
  const string_2 = input2.value;
  resultString = [];
  
  for (let i = 0; i < string_1.length || i < string_2.length; ++i) {
    resultString.push(
      (string_1.charCodeAt(i) || 0) +
      (string_2.charCodeAt(i) || 0)
    );
  }
  
  resultString = String.fromCharCode(...resultString);
  
  result.innerHTML = resultString;
  resultLength.innerHTML = 'Length: ' + resultString.length;
}

input1.addEventListener('input', updateResult);
input2.addEventListener('input', updateResult);

updateResult();
<input id="input1" value="aA"/>
<input id="input2" value="bB"/>

<br/><br/>

<div id="result"></div>
<div id="resultLength"></div>

The shortest code in each programming language wins!

\$\endgroup\$
9
  • 1
    \$\begingroup\$ How does the last test case have \u0083 between the other two instead of being first? \$\endgroup\$ Feb 28 at 16:29
  • 1
    \$\begingroup\$ Suggested tag: string \$\endgroup\$
    – The Thonnu
    Feb 28 at 17:49
  • 1
    \$\begingroup\$ @TheThonnu Added. Thank you! \$\endgroup\$
    – EzioMercer
    Feb 28 at 17:55
  • 2
    \$\begingroup\$ Are the characters guaranteed to be in Unicode Plane 0? \$\endgroup\$
    – alephalpha
    Mar 1 at 1:43
  • 3
    \$\begingroup\$ @alephalpha All symbols will be from range [\u+0000, \u+ffff] \$\endgroup\$
    – EzioMercer
    Mar 1 at 1:45

15 Answers 15

6
\$\begingroup\$

Excel, 92 89 bytes

=CONCAT(
    TOCOL(UNICHAR(MOD(MMULT(IFERROR(UNICODE(MID(A1:B1,ROW(A:A),1)),),{1;1}),4^8)),2)
)

Inputs in cells A1 and B1.

Thanks to JvdV for the 3-byte save.

\$\endgroup\$
6
  • 1
    \$\begingroup\$ 89 Bytes =CONCAT(TOCOL(UNICHAR(MOD(MMULT(IFERROR(UNICODE(MID(A1:B1,ROW(A:A),1)),),{1,1}),4^8)),2)) \$\endgroup\$
    – JvdV
    Mar 1 at 14:53
  • 1
    \$\begingroup\$ @JvdV :-) That's sneaky! TOCOL with 2nd parameter can replace IFERROR! \$\endgroup\$ Mar 1 at 15:01
  • \$\begingroup\$ Would just change your {1,1} to {1;1} for English-language versions maybe. \$\endgroup\$ Mar 1 at 15:01
  • \$\begingroup\$ Woops, yes, that's a typo! \$\endgroup\$
    – JvdV
    Mar 1 at 15:02
  • 1
    \$\begingroup\$ And thanks very much for taking the time to look at and improve upon my posts here. Much appreciated. On a pure byte count it's obviously near impossible to compete with the vast majority of the other languages here, but at least we can keep the Excel flag flying, for what it's worth. \$\endgroup\$ Mar 1 at 15:11
4
\$\begingroup\$

Vyxal, 6 bytes

C∑k₴%C

Try it Online!

How it works:

C∑k₴%C
C∑       Sum codepoints of each word
  k₴%    Push 65535 and modulo by each element
     C   Convert codepoints to words
\$\endgroup\$
3
\$\begingroup\$

Japt, 11 bytes

Takes input as an array of 2 character arrays, outputs a single character array.

ÕËxc uG²² d

Try it

ÕËxc uG²² d     :Implicit input of 2D array
Õ               :Transpose
 Ë              :Map
  x             :  Sum of
   c            :    Codepoints
     u          :  Modulo
      G         :    16
       ²²       :    Squared twice
          d     :  Character at resulting codepoint
\$\endgroup\$
3
\$\begingroup\$

Z80 machine language, 52 bytes

Null-terminated strings, addresses passed in DE and HL; output string address passed in BC. Little-endian.

D5 E5 7E 23 B6 23 EB 28 0A 7E 23 B6 23 EB 20 F4
37 E1 D5 30 03 EB C5 7E 02 23 03 B6 7E 02 23 03
20 F7 E1 1A 47 86 77 13 23 1A 4F 8E 77 13 23 78
B1 20 F2 C9

Disassembled:

f:
    push de         // D5
    push hl         // E5
wl:
    ld a,(hl)       // 7E       // test one wchar of each
    inc hl          // 23
    or (hl)         // B6
    inc hl          // 23
    ex de,hl        // EB
    jr z,fzero      // 28 0A
    ld a,(hl)       // 7E
    inc hl          // 23
    or (hl)         // B6
    inc hl          // 23
    ex de,hl        // EB
    jr nz,wl        // 20 F4
    scf             // 37       // if we have made it here, first was shorter
fzero:
    pop hl          // E1
    pop de          // D5
    jr nc,copy      // 30 03
    ex de,hl        // EB
copy:               //          when we get here, wstrlen(hl)>wstrlen(de)
    push bc         // C5
cl:
    ld a,(hl)       // 7E       // copy a byte
    ld (bc),a       // 02
    inc hl          // 23
    inc bc          // 03
    or (hl)         // B6       // or in the second to see if both 0
    ld a,(hl)       // 7E       // copy the second (preserves flags)
    ld (bc),a       // 02
    inc hl          // 23
    inc bc          // 03
    jr nz,cl        // 20 F7    // if either nonzero, loop again
    pop hl          // E1       // put dest in hl
aloop:
    ld a,(de)       // 1A
    ld b,a          // 47
    add (hl)        // 86
    ld (hl),a       // 77
    inc de          // 13       // *(hl++) += (b = *(de++)
    inc hl          // 23
    ld a,(de)       // 1A
    ld c,a          // 4F
    adc (hl)        // 8E
    ld (hl),a       // 77
    inc de          // 13
    inc hl          // 23       // *(hl++) += (c = *(de++)) + cf
    ld a,b          // 78
    or c            // B1
    jr nz,aloop     // 20 F2    // continue if b|c
    ret             // C9
\$\endgroup\$
3
\$\begingroup\$

Python, 89 bytes

lambda x,y:[chr(sum(map(ord,a))%4**8)for a in zip(f'{x:\0<{len(y)}}',f'{y:\0<{len(x)}}')]

Try it online!

-15 bytes thanks to @SevC_10

\$\endgroup\$
1
  • \$\begingroup\$ Here are some improvements: 1. no need for the external map; 2. use the f-string for padding the strings to equal length; 3. use \0 for the NUL character. Try it online 89 bytes \$\endgroup\$
    – SevC_10
    Mar 1 at 13:36
3
\$\begingroup\$

05AB1E, 7 bytes

0ζOžH%ç

Try it online!

Explanation

0ζOžH%ç  # 05AB1E automatically converts the strings
         # to codepoints since they are delimited by '
0ζ       # Transpose with filler 0
  O      # Sum each inner list
   žH    # Push 65536 
     %   # Mod each value by 65536
      ç  # Convert back from codepoint to character
\$\endgroup\$
3
  • \$\begingroup\$ "05AB1E automatically converts the strings to codepoints since they are in a list" Didn't even knew it did this. o.Ô Nice answer! \$\endgroup\$ Mar 1 at 8:30
  • \$\begingroup\$ I think the reason this works is that items and lists are evaluated by elixir, and '-delimited strings are codepoint lists in Elixir. This is different if you use " as string delimiters \$\endgroup\$
    – ovs
    Mar 1 at 11:03
  • \$\begingroup\$ @ovs oh yeah, you're right. I didn't check that. \$\endgroup\$
    – The Thonnu
    Mar 1 at 16:10
3
\$\begingroup\$

J, 30 27 25 bytes

(65536|+/@,:)&.(3 u:7&u:)

-3 thanks to ovs, and -2 more.

Attempt This Online!

(65536|+/@,:)&.(3 u:7&u:)
             &.            NB. u&.v applies v to both args and u to the results
                           NB. then applies the inverse of v to the results of u
               (3 u:7&u:)  NB. monadic fork
                    7&u:   NB. converts each char to a single unicode codepoint
                3 u:       NB. convert string to a list of codepoints
(65536|+/@,:)              NB. dyadic fork
          ,:               NB. stacks codepoint lists filling with 0s
       +/@                 NB. then sum the columns of the resulting table
 65536|                    NB. mod each sum by 65536
                           NB. inverse of v converts codepoints to chars
\$\endgroup\$
5
  • \$\begingroup\$ I don't think the !.0 is necessary, that seems to be the default behaviour. \$\endgroup\$
    – ovs
    Mar 1 at 11:01
  • \$\begingroup\$ Good catch, I was so focused on trying to get ,. to work... \$\endgroup\$
    – south
    Mar 2 at 1:59
  • \$\begingroup\$ (65536|[+/@,:])&.(3 u:7&u:) alternate 27 \$\endgroup\$
    – south
    Mar 4 at 1:12
  • \$\begingroup\$ Pretty sure you drop [ and ]? \$\endgroup\$
    – ovs
    Mar 4 at 8:29
  • \$\begingroup\$ Huh, yeah. Thanks again \$\endgroup\$
    – south
    Mar 5 at 23:21
2
\$\begingroup\$

Python 3, 76 bytes

f=lambda a,b:a and b and chr(ord(a[0])+ord(b[0])&65535)+f(a[1:],b[1:])or a+b

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Raku, 61 bytes

{utf16(roundrobin(@_».encode('utf16'))».sum X%4⁸).decode}

Try it online!

(The older Raku version on TIO requires a ".new" after the first "utf16" for four additional bytes.)

  • @_ are the string arguments to the function.
  • ».encode('utf16') encodes each of those strings as a utf16 blob object.
  • roundrobin combines corresponding elements of those blobs as lists, like zip, but doesn't stop when the end of the shortest input is reached. roundrobin <1 2>, <3 4 5 6> returns (1 3), (2, 4), (5,), (6,).
  • ».sum converts each of those zipped lists to its sum.
  • X% 4⁸ takes each of those sums modulo 65536. (4⁸ is one byte shorter than 65536.)
  • utf16 converts that list of integers to a utf16 blob.
  • .decode converts that blob into a string.
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 37 bytes

F²⊞υSUMυ⁺ι×ψ⁻L§υ¬ιLι⭆⊟υ℅﹪⁺℅ι℅§ΣυκX⁴¦⁸

Try it online! Link is to verbose version of code. Explanation:

F²⊞υS

Input the two strings.

UMυ⁺ι×ψ⁻L§υ¬ιLι

Pad the shorter to the length of the longer with null bytes.

⭆⊟υ℅﹪⁺℅ι℅§ΣυκX⁴¦⁸

Pairwise add the character codes of the two strings, reduce module 4⁸, then convert back to characters.

\$\endgroup\$
1
\$\begingroup\$

Factor, 38 bytes

[ 0 pad-longest [ + 65536 mod ] 2map ]

Try it online!

  • 0 pad-longest pad the shorter of two sequences with 0s until it is the same length as the longer one
  • [ ... ] 2map map over two sequences with a binary function
  • + 65536 mod add the code points together modulo 65536
\$\endgroup\$
1
\$\begingroup\$

Brachylog, 15 bytes

ạᵐz₁+ᵐ%₆₅₅₃₆ᵐ~ạ

Try it online!

Explanation

ạᵐ               Map to codes
  z₁             Zip without cycling
    +ᵐ           Map sum
      %₆₅₅₃₆ᵐ    Map mod 65536
             ~ạ  Codes to string
\$\endgroup\$
1
\$\begingroup\$

C (gcc) with -fwide-exec-charset=UTF16LE, 78 bytes

Takes inputs in UCS-2 (UTF-16LE) encoding and outputs in UCS-2 (UTF-16LE) encoding. TIO and shells don't seem to like UTF-16: running this from an actual machine and redirecting the output gives the correct results.

Output (in KWrite, UTF-16 encoding):

UTF-16 output

f(i,j,k)short*i,*j;{for(;*i|*j;*i&&i++,*j&&j++)printf("%2$c%c",k>>8,k=*i+*j);}

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

JavaScript, 91 bytes (tsh's method)

With recursion

(a,b)=>(g=i=>a[i]?String.fromCharCode(a[c='charCodeAt'](i)+~~b[c](i))+g(i+1):b.slice(i))(0)

Try it:

f=(a,b)=>(g=i=>a[i]?String.fromCharCode(a[c='charCodeAt'](i)+~~b[c](i))+g(i+1):b.slice(i))(0)

const inputHandler = () => {  
  resultString = f(input1.value, input2.value)
  
  result.innerHTML = resultString;
  resultLength.innerHTML = 'Length: ' + resultString.length;
}

input1.addEventListener('input', inputHandler);
input2.addEventListener('input', inputHandler);

inputHandler();
<input id="input1" value="aA"/>
<input id="input2" value="bB"/>

<br/><br/>

<div id="result"></div>
<div id="resultLength"></div>

JavaScript, 97 bytes

Without recursion

(a,b)=>String.fromCharCode(...[...a].map((s,i)=>(g=c=>c.charCodeAt(j=i)|0)(a)+g(b)))+b.slice(j+1)

Try it:

f=(a,b)=>String.fromCharCode(...[...a].map((s,i)=>(g=c=>c.charCodeAt(j=i)|0)(a)+g(b)))+b.slice(j+1)

const inputHandler = () => {  
  resultString = f(input1.value, input2.value)
  
  result.innerHTML = resultString;
  resultLength.innerHTML = 'Length: ' + resultString.length;
}

input1.addEventListener('input', inputHandler);
input2.addEventListener('input', inputHandler);

inputHandler();
<input id="input1" value="aA"/>
<input id="input2" value="bB"/>

<br/><br/>

<div id="result"></div>
<div id="resultLength"></div>

\$\endgroup\$
1
  • 2
    \$\begingroup\$ a=>b=>(g=i=>a[i]?String.fromCharCode(a[c='charCodeAt'](i)+~~b[c](i))+g(i+1):b.slice(i))(0) \$\endgroup\$
    – tsh
    Mar 2 at 5:51
1
\$\begingroup\$

CJam, 9 bytes

z::i::+:c

Try it online!

Explanation

z::i::+:c # a function taking an array with two strings [x y]
z         # zip; transpose rows with columns (i.e, ["Aa" "BbC"] => ["AB" "ab" "C"]
 ::i      # map `i`nt convert to all values
    ::+   # map add to all values, effectively summing each
       :c # map each summed value to `c`hars
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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