按元素的字符串乘法


28

灵感来自这个挑战(感谢@cairdcoinheringaahing为标题!),你的任务就是用下面的规则来取两个打印的ASCII字符串,并乘其逐元素。

它是如何工作的?

给定两个字符串(例如splitisbn),您将首先截断较长的字符串,使它们具有相等的长度,然后确定其ASCII码

split -> spli -> [115, 112, 108, 105]
isbn  -> isbn -> [105, 115,  98, 110]

下一步将是[0..94]通过减去32每个代码将它们映射到范围:

[115, 112, 108, 105] -> [83, 80, 76, 73]
[105, 115,  98, 110] -> [73, 83, 66, 78]

现在,您将它们乘以逐元素的模95(以保持在可打印范围内):

[83, 80, 76, 73] ⊗ [73, 83, 66, 78] -> [74, 85, 76, 89]

添加32以返回到范围[32..126]

[74, 85, 76, 89] -> [106, 117, 108, 121]

最后一步是将它们映射回ASCII字符:

[106, 117, 108, 121] -> "july"

规则

  • 您将编写一个程序/函数,在两个字符串上实现所描述的步骤,并打印或返回结果字符串
  • 输入格式灵活:您可以使用两个字符串,一个字符串元组,一个字符串列表等。
  • 输入内容可能包含一两个空字符串
  • 输入将是可打印范围([32..126])中的字符
  • 输出要么打印到控制台,要么返回一个字符串
  • 输出允许有尾随空格

测试用例

"isbn", "split"                  -> "july"
"", ""                           -> ""
"", "I don't matter"             -> ""
"             ", "Me neither :(" -> "             "
"but I do!", "!!!!!!!!!"         -> "but I do!"
'quotes', '""""""'               -> 'ck_iKg'
"wood", "hungry"                 -> "yarn"
"tray", "gzip"                   -> "jazz"
"industry", "bond"               -> "drop"
"public", "toll"                 -> "fall"
"roll", "dublin"                 -> "ball"
"GX!", "GX!"                     -> "!!!"
"4 lll 4", "4 lll 4"             -> "4 lll 4"
"M>>M", "M>>M"                   -> ">MM>"

注意:在我使用的第六个测试用例中,引号仅出于可读性'考虑"


允许在输出中保留尾随空格吗?
大公埃里克(Erik the Outgolfer)'17年

@EriktheOutgolfer是的。抱歉,我在发布后添加了它。
'17年

我们可以采用字符串数组的数组吗?abc, def -> [['a', 'b', 'c'], ['d', 'e', 'f']]
完全人类

@totallyhuman我不会这么说。但是,如果在您的语言中,字符串是char的数组,并且char与字符串具有相同的类型,那么我猜这将是有效的。
ბიმო

我们是否可以接受输入作为字符串列表?
扎卡里

Answers:


9

MATL,12字节

c32-p95\32+c

在线尝试!

说明

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

1
管理字符串长度差异的聪明方法。
桑契斯'17

6

果冻15 12字节

z⁶O_32P€‘ịØṖ

在线尝试!

-3感谢Jonathan Allan


尾随空格的nea亵滥用。;)
丹尼斯

@Dennis好吧,这是规则,为什么不滥用呢?
暴民埃里克(Erik the Outgolfer)'17年

我相信您可以通过将niladic原子用于可打印字符来节省3个字节ØṖ,并且z⁶O_32P€‘ịØṖ-您最好再次检查该算法是否有效。
乔纳森·艾伦


5

Python 3中80个 74 71字节

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

感谢@shooqie打高尔夫球3个字节!

在线尝试!


1
71 if you take (s, t) as a tuple: lambda t:''.join(map(lambda x,y:chr((ord(x)-32)*(ord(y)-32)%95+32),*t))
shooqie

5

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!


2
Same trick that was suggested on my answer: lambda*t:''.join(chr(((ord(i)-32)*(ord(j)-32))%95+32)for i,j in zip(*t))
Dennis

2
And same one that I suggested a lot: ((ord(i)-32)*(ord(j)-32))%95+32 => (ord(i)-32)*(ord(j)-32)%95+32 ...
Zacharý

o_o beating Dennis. +1
Zacharý

1
Eh, not really, I just changed to a list comprehension instead of using map. I was just slightly late.
totallyhuman

5

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.


You can save 3 bytes by pulling out -32 and saving those parenthesis, see here.
ბიმო

5

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;
}

1
Welcome to PPCG!
Martin Ender

Welcome to the site! Thanks for your answer, I appreciate it. I have no experience in golfing with C++, but here you'll find some tips. Enjoy your time here!
ბიმო

Also I'm pretty sure you can just submit a function, like this.
ბიმო

Can't you remove the spaces here: #include <string>=>#include<string> and #include <algorithm>=>#include<algorithm>?
Zacharý

In addition you should be able to create a macro equivalent to string and use it accordingly.
Zacharý

3

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

I didn't get the interface of tryapl.org, so here's a TIO for those that want to try it.
ბიმო

There, I put both in there.
Zacharý



2

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.


Can you use (l[i]-32)*(n[i]-32)%95+32?
Zacharý

Why yes, I can. Thanks!
jkelm

1
You need to fully qualify the Console and you can use currying to save a byte. Compile to a Action<string, Action<string>> like l=>n=> and call like ("word")("string")
TheLethalCoder

2

Mathematica, 114 bytes

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


input

["public","toll"]


Is there a way to try it online?
ბიმო

of course, go to sandbox.open.wolframcloud.com/app/objects paste the code, paste input at the end, press shift+enter
J42161217

what "8 chars"?
J42161217

Sorry for the confusion! The message "Thanks!" would have been too short to post just like this, it needed 8 chars more.
ბიმო

3
ok....................................
J42161217

2

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')

2

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!




2

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.


saves a byte. Too bad about the empty string input. Otherwise ø would save a few more.
Emigna

2

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

1

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();
    }
}

I think (((c-32)*(t.Substring(0,l)[i]-32))%95)+32) can be ((c-32)*(t.Substring(0,l)[i]-32)%95+32) (might have screwed up the parens there ... it's looking like lisp!)
Zacharý

1

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!



1

Python 2, 95 73 bytes

  • Thanks @Zacharý for 4 bytes: unwanted brackets removed
lambda x,y:''.join(chr((ord(i)-32)*(ord(j)-32)%95+32)for i,j in zip(x,y))

Try it online!


3
Goodness gracious ... learn to use order of operations! (((ord(x[i])-32)*(ord(y[i])-32))%95)+32 => (ord(x[i])-32)*(ord(y[i])-32)%95+32
Zacharý

1

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.


1

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

1
I think you're not correctly truncating the result to the length of the smaller string (see here).
Dada

You're right. Fixed it at a cost of many bytes
Xcali

1

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)

1

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>"
...

1

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

0

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);

109 bytes: for($i=0;$i<strlen($a=$argv[1])&&$i<strlen($b=$argv[2]);)echo chr((ord($a[$i])-32)*(ord($b[$i++])-32)%95+32); Also, I'm not entirely sure if replacing && with & might also be possible in PHP, reducing it by another byte to 108.
Kevin Cruijssen

0

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))))

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.