This was inspired by a function I recently added to my language Add++. Therefore I will submit an short answer in Add++ but I won't accept it if it wins (it wouldn't be fair)

Don't you hate it when you can multiply numbers but not strings? So you should correct that, right?

You are to write a function or full program that takes two non-empty strings as input and output their multiplied version.

How do you multiply strings? I'll tell you!

To multiply two strings, you take two strings and compare each character. The character with the highest code point is then added to the output. If they are equal, simply add the character to the output.

Strings are not guaranteed to be equal in length. If the lengths are different, the length of the final string is the length of the shortest string. The input will always be lowercase and may contain any character in the printable ASCII range (0x20 - 0x7E), excluding uppercase letters.

You may output in any reasonable format, such as string, list etc. Be sensible, integers aren't a sensible way to output in this challenge.

With inputs of hello, and world!, this is how it works


w > h so "w" is added ("w")
o > e so "o" is added ("wo")
r > l so "r" is added ("wor")
l = l so "l" is added ("worl")
d < o so "o" is added ("worlo")
! < , so "," is added ("worlo,")

So the final output for hello, and world! would be worlo,.

More test cases

(without steps)

input2 => output

programming puzzles & code golf!?
not yet graduated, needs a rehaul => prtgyetmirgduuzzlesneedsde rolful

object => oing

bold => boln

lab0ur win.
the "super bowl" => the0usuwir.

donald j.
trumfefe! => trumlefj.

This is a so shortest code wins! Luok!

  • 46
    \$\begingroup\$ This is the elementwise maximum of the strings, right? That doesn't seem anything like multiplying. \$\endgroup\$
    – xnor
    Commented Jun 8, 2017 at 22:34
  • 5
    \$\begingroup\$ Nitpick: PPCG has graduated, we just didn't get a new design yet. \$\endgroup\$
    – Dennis
    Commented Jun 9, 2017 at 4:02
  • 1
    \$\begingroup\$ Possible relevant: codegolf.stackexchange.com/questions/74809/merging-two-strings/… \$\endgroup\$
    – nmjcman101
    Commented Jun 9, 2017 at 11:40
  • 2
    \$\begingroup\$ The first test case is wrong. It should be "input1","input2" => "input2". \$\endgroup\$
    – user92069
    Commented Mar 14, 2020 at 7:26
  • 1
    \$\begingroup\$ @a'_' That‘s not a test case; it’s a Demonstration of the Format of the other test cases \$\endgroup\$ Commented Mar 14, 2020 at 9:40

72 Answers 72


Go, 131 121 bytes

func f(a,b string)(o string){
if A>B{o+=A}else{o+=B}

Attempt This Online!

  • -10 by @The Thonnu

tinylisp 2, 28 bytes

(\(S T)(,(zip-with max S T)"

Try it at Replit! Example session:

tl2> (\(S T)(,(zip-with max S T)"
(() (S T) (, (zip-with max S T) ""))
tl2> (d F _
tl2> (F "hello," "world!")


The library functions zip-with and max do almost the entire task.* The only catch is that zip-with returns a list of codepoints, and we want a string. The easiest way to convert is to concatenate an empty string using , (short for concat).

* When I first answered this challenge, I had not yet implemented zip-with and max in the standard library. Here's my original 46-byte solution without those functions:

(\(S T)(,(m(p a(\(C D)(?(< C D)D C)))(z S T))"


(\(S T)(,(m(p a(\(C D)(?(< C D)D C)))(z S T))""))
(\                                              ) ; Lambda function
  (S T)                                           ; taking two strings S and T:
                                     (z S T)      ; Zip (-> list of pairs of codepoints)
         (m                                 )     ; Map to each pair:
           (p a                     )             ; Apply to its two items:
               (\                  )              ; Lambda function
                 (C D)                            ; taking two integers C and D:
                      (?(< C D)D C)               ; If C < D, then D, else C (i.e. max)
                                                  ; Now we have a list of codepoints...
       (,                                    "")  ; Concat "", converting to string

PowerShell, 75 bytes

-join(1..(($a,$b=$args)|sort l*)[0].length|%{(,$a[$_-1],$b[$_-1]|sort)[1]})
#            ^input array unpack
#       ^string index generation offset by 1
#                         ^sort by length property, so output length matches shorter input
#                                           ^loop over indices
#                                       max of the two characters^
# ^output join

Save as .ps1 file and run

PS C:\> .\Get-MultipliedString.ps1 'hello,' 'world!'

Previously, 78 bytes:


APL (Dyalog), 22 bytes

Takes two (or more!) strings as right argument.


Try it online!

{ an anonymous function where the right argument is represented by

⎕UCS the symbols from the Unicode Character Set which correspond to the

⌈⌿ maximum value in each column of

⎕UCS the code points from the Unicode Character Set for the

 matrified (matrix from list of strings)


↑¨⍨ each capped at the

⌊/ minimum of

≢¨ the lengths

 of the arguments


  • \$\begingroup\$ A slightly different take {⎕UCS⍺(⌊⍥⍴⍴⌈⍥⎕UCS)⍵} \$\endgroup\$ Commented Mar 9, 2021 at 23:21
  • \$\begingroup\$ @1_am_Jack That's amazing. Why don't you post that yourself? Also, I think it can be just ⎕UCS⌊⍥⍴⍴⌈⍥⎕UCS or as I would put it ⎕UCS⌊⍥≢↑⌈⍥⎕UCS \$\endgroup\$
    – Adám
    Commented Mar 9, 2021 at 23:24
  • \$\begingroup\$ Thanks. tio.run doesn't appear to like that function composition operator... wasn't sure if having a way to try it online was a requirement. \$\endgroup\$ Commented Mar 10, 2021 at 0:09
  • \$\begingroup\$ @1_am_Jack I realise now that it won't work, because ⌈⍥⎕UCS is applied first, and will LENGTH ERROR :-( However, for next time: TIO is running an old version of Dyalog APL. is available in Dyalog Extended or you can "poly-fill" it in the Header field as Ö←{(⍵⍵ ⍺)⍺⍺(⍵⍵ ⍵)} (and then use Ö instead of ). \$\endgroup\$
    – Adám
    Commented Mar 10, 2021 at 5:41
  • \$\begingroup\$ Good to know, thanks for your help. I only came across APL a month ago, your code golf answers have been very helpful 👍 \$\endgroup\$ Commented Mar 10, 2021 at 5:46

Aceto, 43 bytes



First, we read the first string, and explode it, then we move a stack to the left, read the second string, and explode it:


Now, we check for emptiness of either of the stacks and exit if that is the case:


Next, we duplicate the top letter of both stacks, and convert them to code points, then move them both (and us) on the right stack:


The w tests if something is less or equal. If so, we get mirrored to the right. Otherwise, we print the top letter, go on the left stack, drop the top element (the other letter) and move up (^), which moves us on the bottom <, which moves us back to the length check.


If however, the test was truthy, we get mirrored into the emptiness on the right, and we need to do the opposite. Eventually we reach the three commands that now drop, then move to the left stack and print its top element. The < is the same symbol we land on in the other case, so here too we are lead back to the length check.


This repeats until one of the length checks succeeds, i.e. if one of the input strings is exhausted.


k, 14 bytes




q translation:

{max(min count each x)$/:x}

Free interpreter available here

  • 1
    \$\begingroup\$ Can you provide a Try It Online or similar? At the moment, K doesn't produce the correct output on Kona or oK \$\endgroup\$ Commented Jul 14, 2017 at 19:36
  • \$\begingroup\$ I added a link to download the interpreter. Kona is an implementation of an old version of k. oK is an implementation of the k6 spec (kparc.com/k.txt), which doesn't have a reference implementation from kx yet. \$\endgroup\$
    – skeevey
    Commented Jul 14, 2017 at 19:46

J, 22 bytes


Try it online!


0({"1\:~@,"0/)<.&#$&>;  Input: string x (LHS), string y (RHS)
                 #      Get length of x and y
              <.&       Minimum of those
                     ;  Link x and y as a pair of boxed strings
                  $&>   Shape each to the minimum length
         ,"0/           Reduce by joining elementwise
     \:~@               Grade down each pair
0 {"1                   Select the value at index 0 from each
  • \$\begingroup\$ unfortunately my idea f=:{.@/:~"1@|:@,: has trailing spaces and fails when one or other string is one character long \$\endgroup\$
    – jayprich
    Commented May 25, 2018 at 2:34

Java 8 + Eclipse Collections, 70 64 bytes


a and b are both MutableList<Character> from eclipse collections.


Java, 158 151 bytes


String s(String a,String b){String r="";for(int i=0;i<Math.min(a.length(),b.length());i++){char c=a.charAt(i);char d=b.charAt(i);r+=c>d?c:d;}return r;}


String s(String a,String b) {
    String r = "";
    for(int i=0; i < Math.min(a.length(),b.length()); i++) {
        char c = a.charAt(i);
        char d = b.charAt(i);
        r += c > d ? c : d; //absolute ternary abuse
    return r;

Takes two strings in a and b.

  • \$\begingroup\$ I think you could save a few bytes by getting rid of the outside ternary if statement (r+=c==d?c:) since if they are equal you can add either c or d to the string and it won't make a difference. \$\endgroup\$
    – 0 '
    Commented Dec 8, 2017 at 2:18
  • \$\begingroup\$ 79 bytes: a->b->r->{for(int i=0;i<a.length&i<b.length;i++)r.append(a[i]>b[i]?a[i]:b[i]);}, which is a Function<char[],Function<char[],Consumer<StringBuilder>>> and outputs by modifying the StringBuilder. \$\endgroup\$
    – corvus_192
    Commented Oct 27, 2022 at 7:52

Prolog (SWI), 55 bytes


Try it online!


Japt, 9 bytes

Can't seem to do better than 9. Takes input as a 2D array of characters, outputs an array of characters


Try it (header formats the input)

ñÊÕfÎËñ Ì     :Implicit input of 2D array
ñ             :Sort by
 Ê            :  Length
  Õ           :Transpose, padding the shorter array with null if necessary
   f          :Filter by
    Î         :  First element (removing the arrays that contain null)
     Ë        :Map
      ñ       :  Sort
        Ì     :  Last element

Knight, 70 51 48 bytes

;=aP;=bP W&a b;O+A I>a bAaAb"\";=aGa 1La=bGb 1Lb

Try it online!

Ungolfed & explained:

; = a PROMPT                                  # a = input()
; = b PROMPT                                  # b = input()
: WHILE & a b                                 # while a != "" and b != "":
    ; OUTPUT + ASCII IF > a b ASCII           #
               a ASCII b "\"                  #    print(a[0] if a > b else a[1]) # (without newline)
    ; = a GET a 1 LENGTH a                    #    a = a[1:]
    : = b GET b 1 LENGTH b                    #    b = b[1:]

-19 bytes thanks to Adam.

-3 bytes thanks to Bubbler.

  • \$\begingroup\$ 51 bytes: ;=aP;=bP W&a b;O+I>AaAbA AaA Ab"\";=aGa 1La=bGb 1Lb. However, I think this program relies on undefined behavior for GET, since (LENGTH a)+1 is outside the bounds of the string. \$\endgroup\$ Commented Aug 3, 2022 at 22:52
  • \$\begingroup\$ @Adam Thanks. Undefined behavior is accepted as long as it works. \$\endgroup\$
    – naffetS
    Commented Aug 3, 2022 at 22:53
  • \$\begingroup\$ Oh, I didn't know that, thanks. \$\endgroup\$ Commented Aug 3, 2022 at 22:53
  • \$\begingroup\$ You can factor out the A of A Aa and A Ab out of I, and simplify >AaAb to >a b (because a>b guarantees a[0]>=b[0] and not(a>b) guarantees a[0]<=b[0]). \$\endgroup\$
    – Bubbler
    Commented Aug 3, 2022 at 23:54
  • \$\begingroup\$ @Bubbler It doesn't actually save bytes to factor out A A because then it requires more spaces. It does save 1 though by using >a b \$\endgroup\$
    – naffetS
    Commented Aug 4, 2022 at 0:28

Arturo, 22 bytes


Try it

Takes and outputs a list of characters.


Rust, 34 bytes


which takes in two iterators over chars and returns another. This only works by shunting the following obscene type into the header code:

for<'a> fn(std::str::Chars<'a>, std::str::Chars<'a>) -> std::iter::Map<std::iter::Zip<std::str::Chars<'a>, std::str::Chars<'a>>, fn((char, char))->char>

Attempt This Online!

If iterators over chars do not count as reasonable input/output I can instead manage

60 bytes


which has the much more reasonable type of

fn(&str, &str) -> String

Attempt This Online!


Mathematica, 102 bytes



["blended ", "bold"]

  • \$\begingroup\$ L@a~Min~L@b saves one byte \$\endgroup\$ Commented Jun 9, 2017 at 0:00

Micro, 119 bytes

{R b i m+:R}:X{R a i m+:R}:Y
b a<if(N,)
a i m C b i m C~:> if(X,Y)
i M=if(,Z)}:Z

C#, 71, 67 bytes

saved a few bytes by using string.Join() instead of new string()

added 18 bytes to both versions for needing using System.Linq;

67 bytes


71 bytes:

(a,b)=>new string(a.Zip(b,(x,y)=>x>y?x:y).ToArray());



Modern Pascal

version 1 of algorithm (func:139bytes)

   for var l:=1 to min(length(paramstr(1)),length(paramstr(2))) do

Explanation The for loop is designed to crawl to the length of the shortest string. The output is compared appending to result the highest ASCII value of each letter crawled. Since we are using shortest length, we can access the strings elements directly - see v2 below, uses Copy() to be safer.

version 2 of algorithm (func:166bytes)

   for var l:=1 to max(length(paramstr(1)),length(paramstr(2))) do

// Author of Modern Pascal

  • \$\begingroup\$ Welcome to our site! This contest is a code-golf contest. You should aim to minimize the number of bytes in the source code. I don't know pascal at all so this may be well golfed already but I suspect there is some whitespace that can be removed. Once you are satisfied with your golfs you can add the byte count of your program to your header. If you have any questions you can ping me with @wheatwizard. \$\endgroup\$
    – Wheat Wizard
    Commented Jun 12, 2017 at 13:49
  • 1
    \$\begingroup\$ As Wheat Wizard said, I'm sure this can be golfed to reduce your score but I think that there is at least one typo in your first code, maybe two. Should iif(a[l]>b[l]),a[l] be if(a[l]>b[l],a[l]? (there is definitely an extra ) but I don't know about iif and if) \$\endgroup\$ Commented Jun 12, 2017 at 14:13
  • \$\begingroup\$ shortened. Good find on the extra paren. fixed. In MP, I added iff() to mimic ?(eval,true,false). \$\endgroup\$
    – Ozz Nixon
    Commented Jun 13, 2017 at 17:39

Charcoal, 17 bytes


Try it online! Link is to verbose version of code. Edit: Slice got added a few days later, which would have allowed the following code for 15 bytes: Try it online!

  • \$\begingroup\$ 9 bytes instead of 15, not sure if I had this back in June so maybe it's valid lol :P tio.run/##S85ILErOT8z5/… \$\endgroup\$
    – ASCII-only
    Commented Aug 28, 2017 at 15:41

Pip, 9 bytes


Try it online!

Pip doesn't have a string max operator, so I used SS (Sort String) instead:

      aZb  Zip the two cmdline args together, truncating to shorter length
     M     To that list of 2-element lists of characters, map a function:
  SS_       Sort each pair of characters stringwise
DQ          and dequeue the second (larger) one
           Autoprint the resulting list of characters

Acc!!, 186 bytes

Count i while _/128^i/32 {
Count i while _%128/32*(_/4096) {
Count j while _/128%128/(_%128+1) {
Write _%128

Input strings should be given on stdin, newline-separated. Try it online!


We conceptually partition the accumulator into 7-bit registers, each of which can hold an input character. The first Count i loops until the input's ASCII code is smaller than 32, storing the first line of input into the accumulator, with the first character in the least-significant position:

, o l l e h
5 4 3 2 1 0
Accumulator value = asc(h) + 128*asc(e) + 128^2*asc(l) + ... = 1541853098728

Next, we shift everything left by one register, read the first character of the second line, and store it into register 0:

, o l l e h w
6 5 4 3 2 1 0

We Count i again while register 0 (_%128) and register 1 (_/128%128, though the formula can be golfed a bit in this context) are both >= 32. Inside the loop, we use a nested Count j loop to check if register 1 is strictly greater than register 0. (Comparisons are done via integer division: if a/(b+1) is 0, then a<=b; if a/(b+1) is nonzero, then a>b.) If it is greater, we swap the registers' contents. This loop executes at most once, because after swapping, the condition is guaranteed not to be true anymore.

After the (potential) swap, the larger of the two characters is in register 0, which we output. We then shift two registers to the right (_/128^2), shift one register back to the left (*128), and store the next input character in register 0 (+N):

, o l l e o
5 4 3 2 1 0

The Count i loop exits once one or both strings reach the newline at their end.


Common Lisp, 59 bytes

(lambda(x y)(map'string(lambda(a b)(if(char> a b)a b))x y))

Try it online!


Axiom, 67 20 bytes


And with this we now surpass JavaScript, Lisp until perhaps J and APL too.

The previous solution:

f(a,b)==concat[max(a.x,b.y)::String for x in 1..#a for y in 1..#b]

Whispers, 49 bytes

> Input
> Input
>> L»R
>> Each 3 1 2
>> Output 4

Try it online!

How it works

Each line consists of (line no.) (> or >>) (command) (the line numbers are implicitly added in the actual program)

1 > Input        - Retrieve the first input

2 > Input        - Retrieve the second input

3 >>  »          - Take the maximum of...
     L           -   the left argument and...
       R         -   the right argument

4 >> Each        - For each value in...
            1    -   the first line zipped with...
              2  -   the second input,
          3      -   call the third line

5 >>        4    - Run the fourth line, then...
     Output      - Output the result

Swift, 66 bytes

func f(a:String,b:String){print(String(zip(a,b).map{max($0,$1)}))}

Straight forward solution


Japt v2.0a0, 13 bytes


Try it online!

Unpacked & How it works

Ul mVl)îUcXYZ{XwVcY

Ul      Length of 1st input (U)
mVl)    Minimum of above and length of 2nd input (V)
î       Take this length out of the following string...
UcXYZ{    Map on charcodes of U and convert back to string...
Xw          Maximum of this and...
VcY         V's charcode at the same index.

Japt doesn't have min/max on strings, but does have one on numbers. Turns out that it helped reduce bytes on both "Compute minimum length of two strings" and "Map on two strings to take higher chars".


Cjam, 3 bytes

This is so easy...


Pretty much the same as the Haskell answer, . takes an operator and performs "zipWith", and e> means take the max of the two inputs.

Try it online!


GolfScript, 23 bytes


Try it online!


R, 96 bytes

for(i in 1:min(lengths(m<-sapply(scan(,""),utf8ToInt))))cat(intToUtf8(max(m[[1]][i],m[[2]][i])))

Try it online!

Using ASCII code.


Burlesque, 9 bytes


Try it online!

Returns a list of characters add 2 bytes for concat (\[)

ln  # Split on newlines
p^  # Push to arr
q>] # Boxed maximum
Z[  # ZipWith

Your Answer

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

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