g | x | w | all
Bytes Lang Time Link
057Janet250722T113857ZAdam
nan250722T101943ZRARE Kpo
011Itr230818T104801Zbsoelch
062jq230818T110904ZGammaFun
082Zsh230818T104130ZGammaFun
012Thunno 2 B230818T101645ZThe Thon
088Ruby221027T025254ZJordan
016Vyxal220703T013411ZnaffetS
081Red220612T060604Zchunes
039Factor210326T091955Zchunes
065Kotlin200323T103137Zsnail_
095Java 8171023T123347ZKevin Cr
01505AB1E180327T232521ZMagic Oc
089JavaScript ES6171204T115319Zedc65
026K oK171204T104549Zmkst
045Factor171204T071221Zfede s.
019Pip171204T055704ZDLosc
148C++170721T194635ZHatsuPoi
113D170904T163543ZAdalynn
065Perl 5170728T083838ZDada
095Perl 5170727T052751ZXcali
112PHP170727T191141Zhalfmang
275FSharp170724T111624ZLaco
030Charcoal170722T143551ZNeil
073Python 2170721T162411Z0xffcour
024Japt170721T214527ZJustin M
099Common Lisp170721T203914ZRenzo
088R170721T201309ZGiuseppe
012Jelly170721T154846ZErik the
057Haskell170721T174851ZLaikoni
024Dyalog APL170721T160627ZAdalynn
052Stacked170721T170553ZConor O&
070Python 2170721T163409Ztotallyh
071Python 3170721T161907ZDennis
114Mathematica170721T161939ZZaMoC
095C# .NET Core170721T160955Zjkelm
023CJam170721T160909ZErik the
012MATL170721T153616ZLuis Men
166C#170721T154501ZTheLetha

Janet, 57 bytes

|(string/from-bytes;(map|(+(%(*;(map - $&"  "))95)32);$))                                                                               

Takes a tuple of two strings.

Surely there has to be a better way to convert an array of bytes to a string than string/from-bytes

The congruence math means one isn't constrained by just -32 :

return 32 + (x + 63) * (y + 63) % (32 + 63)

gives you the same result.

Itr, 11 bytes

32â-R*95%+¥

Takes input as an array of 2 strings

prints additional trailing spaces if one string is longer

online interpreter

Explanation

32â-R*95%+¥ ; implicit input
32          ; constant 32
  â         ; push 32 below implicit input
   -        ; subtract 32 from input
    R*      ; multiply elements of input array
      95%   ; take input modulo 95
         +  ; add 32
          ¥ ; print value as string (implicit output will print '()' for empty string)

jq, 62 bytes

map(explode)|transpose|map((.[0]-32)*(.[1]-32)%95?+32)|implode

Attempt This Online!

transpose fills in null for missing elements, we suppress those with ?.

Zsh, 82 bytes

s=
repeat $#1 ((#2))&&s+=${(#)$((32+(#1-32)*(#2-32)%95))}&&1=${1:1} 2=${2:1}
<<<$s

Attempt This Online!

The flags needed to emulate zip() added too many characters, so we instead repeat for the length of the first argument, and check ((#2)) to see if we've reached the end of the second argument.

Thunno 2 B, 12 bytes

Z32-€p95%32+

Try it online!

Explanation

Z32-€p95%32+  # Implicit input (converted to ordinals)
Z             # Zip them together (truncate longer one)
 32-          # Subtract 32 (vectorised)
    €p        # Product of each inner pair
      95%     # Modulo by 95 (vectorised)
         32+  # Add 32 (vectorised)
              # Implicit output (converted to string)

Ruby, 88 bytes

->a{c,d=a.map{_1[0,a.map(&:size).min].bytes}
c.map{((_1-32)*(d.shift-32)%95+32).chr}*""}

Attempt This Online!

Vyxal, 16 bytes

øŀC32-ƒ*95%32+Cṅ

Try it Online!

øŀC32-ƒ*95%32+Cṅ  # Example input: ["wood", "hungry"]
øŀ                # Align to left by padding to the right with spaces: ["wood  ", "hungry"]
  C               # Character codes: [[119, 111, 111, 100, 32, 32], [104, 117, 110, 103, 114, 121]]
   32-            # Subtract 32: [[87, 79, 79, 68, 0, 0], [72, 85, 78, 71, 82, 89]]
      ƒ*          # Element-wise multiply both: [6264, 6715, 6162, 4828, 0, 0]
        95%       # Modulo 95: [89, 65, 82, 78, 0, 0]
           32+    # Add 32: [121, 97, 114, 110, 32, 32]
              C   # From character codes: ["y", "a", "r", "n", " ", " "]
               ṅ  # Join together: "yarn  "

Red, 81 bytes

func[a b][repeat i min length? a length? b[prin a/:i - 32 *(b/:i - 32)% 95 + 32]]

Try it online!

Factor, 39 bytes

[ [ [ 32 - ] bi@ * 95 mod 32 + ] 2map ]

Try it online!

Explanation:

This is a quotation (anonymous function) that takes two strings from the data stack and leaves one string on the data stack. In Factor, strings are just sequences of unicode code points and can be manipulated like any other sequence.

Kotlin, 65 bytes

{zip(it){a,b->(a-' ')*(b-' ')%95+32}.fold(""){s,i->s+i.toChar()}}

Try it online!

Java 8, 127 115 97 95 bytes

a->b->{for(int i=0;i<a.length&i<b.length;System.out.printf("%c",(a[i]-32)*(b[i++]-32)%95+32));}

Explanation:

Try it here.

a->b->{                       // Method with 2 char-array parameters and no return-type
  for(int i=0;                //  Index-integer, starting at 0
      i<a.length&i<b.length;  //  Loop over both arrays up to the smallest of the two
    System.out.printf("%c",   //   Print, as character:
      (a[i]-32)               //    Current char of `a` minus 32
      *(b[i++]-32)            //    multiplied with current char of `b` minus 32
      %95                     //    Take modulo-95 of that multiplied result
      +32));}                 //    And add 32 again

05AB1E, 16 15 bytes

.BÇ32-`*₃%32+çJ

Try it online!

-1 for Emigna pointing out pushes 95.


                 # ['hi', 'you']
.B               # [['hi ', 'you']]
  Ç              # [[[104, 105, 32], [121, 111, 117]]]
   32-           # [[[72, 73, 0], [89, 79, 85]]]
      `          # [[72, 73, 0], [89, 79, 85]]
       *         # [[6408, 5767, 0]]
        ₃%       # [[43, 67, 0]]
          32+    # [[75, 99, 32]]
             ç   # [['K', 'c', ' ']]
              J  # ['Kc ']

.BÇ32-`*95%žQsèJ

is another.

JavaScript (ES6), 89 bytes

Javascript and the curse of the lengthy function names ...

Using currying and the fact that charCodeAt returns NaN when called with an invalid position. There can be trailing nulls in the output.

a=>b=>a.replace(/./g,(c,i)=>String.fromCharCode((z=x=>x.charCodeAt(i)-32)(a)*z(b)%95+32))

Test

var f=
a=>b=>a.replace(/./g,(c,i)=>String.fromCharCode((z=x=>x.charCodeAt(i)-32)(a)*z(b)%95+32))

q=x=>'['+x+']'

;[["isbn", "split"],["", ""],["", "I don't matter"],["             ", "Me neither :("],
["but I do!", "!!!!!!!!!"],['quotes', '""""""'],["wood", "hungry"],["tray", "gzip"],
["industry", "bond"],["public", "toll"],["roll", "dublin"],["GX!", "GX!"],
["4 lll 4", "4 lll 4"],["M>>M", "M>>M"]]
.forEach(([a,b])=>console.log(q(a)+' x '+q(b)+' --> '+q(f(a)(b))))

K (oK), 26 bytes

Solution:

`c$32+95!*/-32+(&/#:'x)$x:

Try it online!

Example:

`c$32+95!*/-32+(&/#:'x)$x:("split";"isbn")
"july"

Explanation:

Evaluation is performed right-to-left:

`c$32+95!*/-32+(&/#:'x)$x: / the solution
                        x: / assign input to variable x
                       $   / pad right to length on left
               (  #:'x)    / count each x (return length of each char list in list)
                &/         / min-over, get the minimum of these counts
           -32+            / subtract 32, this automagically converts chars -> ints
         */                / multiply-over, product of the two lists
      95!                  / modulo 95
   32+                     / add 32 back again
`c$                        / convert to character array

Factor, 45

[ [ [ 32 - ] bi@ * 95 mod 32 + ] "" 2map-as ]

It's a quotation (lambda), call it with two strings on the stack, leaves the new string on the stack.

As a word:

: s* ( s1 s2 -- ps ) [ [ 32 - ] bi@ * 95 mod 32 + ] "" 2map-as ;

"M>>M" "M>>M" s*      ! => ">MM>"
dup s*                ! => "M>>M"
dup s*                ! => ">MM>"
...

Pip, 19 bytes

(PA$* *(PA@?Zg)%95)

Takes the strings as command-line arguments. Try it online!

Explanation

(PA$* *(PA@?Zg)%95)
                     g is list of args; PA is string of all printable ASCII characters
            Zg       Zip items of g together: result is list of pairs of characters
        PA@?         Find index of each character in PA
       (      )      (Parentheses to get correct operator precedence)
   $* *              Map (fold on *) to the list: multiplies each pair of numbers
               %95   Take list items mod 95
(PA               )  Use those numbers to index into PA again
                     Print the resulting list of chars, concatenated together (implicit)

C++, 331 291 282 270 268 bytes, Version 2 = 178 176 150 148 bytes

Original Version :

#include<string>
#include<algorithm>
#define L length()
#define S std::string
S m(S a,S b){S c;int m=a.L<b.L?a.L:b.L;auto l=[m](S&s){s=s.substr(0,m);std::for_each(s.begin(),s.end(),[](char&c){c-=32;});};l(a);l(b);for(int i=0;i<m;++i){c+=a[i]*b[i]%95+32;}return c;}

-40 bytes thanks to Bruce Forte
-39 bytes thanks to Zacharý

Version 2, inspired by other people's answers

#include<string>
#define L length()
using S=std::string;S m(S a,S b){S c;for(int i=0;i<(a.L<b.L?a.L:b.L);++i)c+=(a[i]-32)*(b[i]-32)%95+32;return c;}

If the first version uses a lambda, it's because i wanted to test C++11 std::async function i just learnt before, so i kept it for no reasons...

More readable version :

#include<iostream>
#include<string>
#include<algorithm>

using namespace std;

#define L length()
#define S string

//Function code for the original version
S m(S a,S b) {
    S c;
    int m = a.L < b.L ? a.L : b.L;

    auto l=[m](S&s){
        s = s.substr(0, m);
        for_each(s.begin(),s.end(),[](char&c){
            c -= 32;
        });
    };
    l(a);
    l(b);
    for(int i=0;i<m;++i) {
        c += a[i] * b[i] % 95 + 32;
    }
    return c;
}

//Code for the version 2
S m2(S a,S b) {
    S c;
    for(int i = 0; i < (a.L < b.L ? a.L : b.L); ++i) {
        c += (a[i] - 32) * (b[i] - 32) % 95 + 32;
    }
    return c;
}

int main() {
    string a, b, c;
    getline(cin, a);
    getline(cin, b);
    c = m(a, b);
    cout << c;
}

D, 113 bytes

T m(T)(T a,T b){T c;for(int i;i<(a.length<b.length?a.length:b.length);++i)c~=(a[i]-32)*(b[i]-32)%95+32;return c;}

This is a port of HatsuPointerKun's C++ solution, don't forget to upvote them!

Try it online!

Perl 5, 65 bytes

64 bytes of code + -p flag.

$n=reverse<>;s/./($_=chop$n)&&chr 32+(-32+ord$&)*(-32+ord)%95/ge

Try it online!

Perl 5, 95 bytes

@a=<>=~/(.)/g;@b=<>=~/(.)/g;$#a=$#b if@a>@b;print chr 32+(-32+ord$_)*(-32+ord$b[$i++])%95 for@a

Try it online!

Explanation:

@a=<>=~/(.)/g;@b=<>=~/(.)/g;  # Split the strings into 2 arrays
$#a=$#b if@a>@b;              # Truncate the first if longer than the second
print chr 32+(-32+ord$_)*(-32+ord$b[$i++])%95 for@a  # Multiply each character

PHP, 112 bytes

for($i=0;$i<min(strlen($a=$argv[1]),strlen($b=$argv[2]));$i++)echo chr((ord($a[$i])-32)*(ord($b[$i])-32)%95+32);

FSharp 275 bytes

let f (p : string, q : string) =     
let l = if p.Length < q.Length then p.Length else q.Length
p.Substring(0,l).ToCharArray() |> Array.mapi (fun i x -> (((int(x) - 32) * (int(q.[i]) - 32)) % 95) + 32) |> Array.map (fun x -> char(x).ToString()) |> Array.fold(+) ""

Charcoal, 30 bytes

F⌊⟦LθLη⟧℅⁺³²﹪×⁻³²℅§θι⁻³²℅§ηι⁹⁵

Try it online! Link is to verbose version of code. I actually wrote the calcualation as (32 - ord(q)) * (32 - ord(h)) because it avoids consecutive numeric literals but I guess I could have just written (ord(q) - ord(" ")) * (ord(h) - ord(" ")) instead.

Python 2, 95 73 bytes

lambda x,y:''.join(chr((ord(i)-32)*(ord(j)-32)%95+32)for i,j in zip(x,y))

Try it online!

Japt, 24 bytes

¬íVq)®®©c -HÃ×u95 +H dÃq

Returns a string with trailing null-chars (\u0000) when the first input is longer than the second.

Try it online! with the -Q flag to show formatted output, including the null-chars.

Run all the test cases using my WIP CodePen.

Common Lisp, 99 bytes

(lambda(a b)(map'string(lambda(x y)(code-char(+(mod(*(-(#1=char-code x)32)(-(#1#y)32))95)32)))a b))

Try it online!

R, 88 bytes

function(r,s,u=utf8ToInt)intToUtf8((((u(r)-32)*(u(s)-32))%%95+32)[0:min(nchar(c(r,s)))])

anonymous function; takes input as two strings; third argument is just to ensure this is a one line function and save some bytes.

The TIO link below returns an array with entries named with the first input.

Try all test cases!

Jelly, 15 12 bytes

z⁶O_32P€‘ịØṖ

Try it online!

-3 thanks to Jonathan Allan.

Haskell, 60 57 bytes

zipWith(\a b->toEnum$f a*f b`mod`95+32)
f=(-32+).fromEnum

Try it online!

First line is an anonymous function taking two arguments.

This a straight forward implementation of the algorithm: zipWith takes both strings and applies a given function to the pairs of characters. It handles the truncation and also works for empty strings. fromEnum and toEnum are alternatives to ord and chr to switch between characters and their ASCII values which do not need a lengthy import.

Edit: -3 bytes thanks to Bruce Forte.

Dyalog APL, 36 34 33 25 24 bytes

{⎕UCS 32+95|×⌿32-⎕UCS↑⍵}

Try it online (TryAPL)!

Try it online (TIO)!

Input is a list of strings, and has trailing whitespace.

Here's how it works:

{⎕UCS 32+95|×⌿32-⎕UCS↑⍵}
                     ↑⍵ - the input as a 2d array
                 ⎕UCS   - codepoints
              32-       - subtract 32
            ×⌿          - element wise product reduction ([a,b]=>a×b)
         95|            - Modulo 95
      32+               - Add 32
 ⎕UCS                   - Unicode characters

Stacked, 52 bytes

[,:$#'"!MIN$take"![CS#.toarr]"!32-prod 95%32+#:''#`]

Try it online!

Function that takes two arguments from the stack.

Explanation

[,:$#'"!MIN$take"![CS#.toarr]"!32-prod 95%32+#:''#`]

Let's look at the first part, assuming the top two items are 'split' and 'isbn':

,:$#'"!MIN$take"!      stack:                      ('split' 'isbn')
,                      pair top two:               (('split' 'isbn'))
 :                     duplicate:                  (('split' 'isbn') ('split' 'isbn'))
  $#'                  length function literal:    (('split' 'isbn') ('split' 'isbn') $#')
    "!                 execute on each:            (('split' 'isbn') (5 4))
      MIN              obtain the minimum:         (('split' 'isbn') 4)
         $take         "take" function literal:    (('split' 'isbn') 4 $take)
                       (e.g. `'asdf' 2 take` is `'as'`)
              "!       vectorized binary each:     (('spli' 'isbn'))

This part performs the cropping.

Then:

[CS#.toarr]"!     stack: (('spli' 'isbn'))
[         ]"!     perform the inside on each string
                  string `'spli'`:
 CS               convert to a character string:    $'spli'
   #.             vectorized "ord":                 (115 112 108 105)
     toarr        convert to array:                 (115 112 108 105)
                  (needed for empty string, since `$'' #.` == `$''` not `()`

Then, the last part:

32-prod 95%32+#:''#`  stack: (((115 112 108 105) (105 115  98 110)))
32-                   subtract 32 from each character code:   (((83 80 76 73) (73 83 66 78)))
   prod               reduce multiplication over the array:   ((6059 6640 5016 5694))
        95%           modulus 95:                             ((74 85 76 89))
           32+        add 32:                                 ((106 117 108 121))
              #:      convert to characters:                  (('j' 'u' 'l' 'y'))
                ''#`  join:                                   ('july')

Python 2, 75 70 bytes

-3 bytes thanks to Dennis' suggestion of shooqie's suggestion. -2 bytes thanks to Zacharý's suggestion.

lambda*l:''.join(chr((ord(i)-32)*(ord(j)-32)%95+32)for i,j in zip(*l))

Try it online!

Python 3, 80 74 71 bytes

lambda*t:''.join(map(lambda x,y:chr((ord(x)-32)*(ord(y)-32)%95+32),*t))

Thanks to @shooqie for golfing off 3 bytes!

Try it online!

Mathematica, 114 bytes

(a=Min@StringLength[x={##}];FromCharacterCode[Mod[Times@@(#-32&/@ToCharacterCode/@(StringTake[#,a]&/@x)),95]+32])&


input

["public","toll"]

C# (.NET Core),100 96 95 bytes

(l,n)=>{for(int i=0;i<l.Length&i<n.Length;)Console.Write((char)((l[i]-32)*(n[i++]-32)%95+32));}

Try it online!

-4 bytes thanks to @Zacharý

-1 byte by moving the increment

Uses a lambda and abuses the fact that characters are basically ints.

CJam, 23 bytes

{z{2' e]' f-:*95%' +}%}

Try it online!

MATL, 12 bytes

c32-p95\32+c

Try it online!

Explanation

c      % Implicitly input cell array of 2 strings. Convert to 2-row char matrix.
       % This pads the shorter string with spaces
32-    % Subtract 32, element-wise. Each char is interpreted as its ASCII code.
       % Note that padding spaces will give 0.
p      % Product of each column. Since (padding) spaces have been mapped to 0, the
       % product effectively eliminates those colums. So the effect is the same as
       % if string length had been limited by the shorter one
95\    % Modulo 95, element-wise
32+    % Add 32, element-wise
c      % Convert to char. Implicitly display

C#, 166 bytes

using System.Linq;s=>t=>{int e=s.Length,n=t.Length,l=e>n?n:e;return string.Concat(s.Substring(0,l).Select((c,i)=>(char)((((c-32)*(t.Substring(0,l)[i]-32))%95)+32)));}

I'm sure there's a lot of golfing to be done but I don't have time right now.

Try it online!

Full/Formatted Version:

using System;
using System.Linq;

class P
{
    static void Main()
    {
        Func<string, Func<string, string>> f = s => t =>
        {
            int e = s.Length, n = t.Length, l = e > n ? n : e;

            return string.Concat(s.Substring(0, l).Select((c, i) => (char)((((c - 32) * (t.Substring(0, l)[i] - 32)) % 95) + 32)));
        };

        Console.WriteLine(string.Concat(f("split")("isbn")));

        Console.ReadLine();
    }
}