Elementweise String-Multiplikation


28

Inspiriert von dieser Herausforderung (danke an @cairdcoinheringaahing für den Titel!) Besteht Ihre Aufgabe darin, zwei druckbare ASCII-Zeichenfolgen zu nehmen und sie mit den folgenden Regeln elementweise zu multiplizieren.

Wie funktioniert es?

Bei zwei gegebenen Zeichenfolgen (zum Beispiel splitund isbn) kürzen Sie zuerst die längere Zeichenfolge so, dass sie die gleiche Länge hat, und bestimmen dann ihren ASCII-Code :

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

Der nächste Schritt besteht darin, sie [0..94]durch Subtrahieren 32jedes Codes dem Bereich zuzuordnen :

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

Jetzt multiplizieren Sie sie elementweise modulo 95(um im druckbaren Bereich zu bleiben):

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

Hinzufügen 32, um zum Bereich zurückzukehren [32..126]:

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

Und der letzte Schritt ist, sie wieder ASCII-Zeichen zuzuordnen:

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

Regeln

  • Sie schreiben ein Programm / eine Funktion, die die beschriebenen Schritte in zwei Zeichenfolgen implementiert und die resultierende Zeichenfolge entweder ausgibt oder zurückgibt
  • Das Eingabeformat ist flexibel: Sie können zwei Zeichenfolgen, ein Tupel von Zeichenfolgen, eine Liste von Zeichenfolgen usw. verwenden.
  • Die Eingabe kann aus einer oder zwei leeren Zeichenfolgen bestehen
  • Die Eingabe erfolgt in Zeichen im druckbaren Bereich ( [32..126])
  • Die Ausgabe wird entweder auf die Konsole gedruckt oder Sie geben eine Zeichenfolge zurück
  • Die Ausgabe darf abschließende Leerzeichen enthalten

Testfälle

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

Hinweis : Die Zitate sind nur zur besseren Lesbarkeit, ich im 6. Testfall verwendet 'statt ".


Dürfen Sie in Ihrer Ausgabe nachgestellte Leerzeichen verwenden?
Erik der Outgolfer

@EriktheOutgolfer Ja. Sorry, das habe ich nach dem Posten hinzugefügt.
21.

Können wir eine Reihe von Reihen von Zeichenfolgen nehmen? abc, def -> [['a', 'b', 'c'], ['d', 'e', 'f']]
Totalhuman

@totallyhuman würde ich nicht so sagen. Wenn Strings in Ihrer Sprache Arrays aus Zeichen sind und Zeichen den gleichen Typ wie Strings haben, dann ist es meiner Meinung nach gültig.
21.

Dürfen wir Eingaben als Liste von Zeichenfolgen annehmen?
Zacharý

Antworten:


9

MATL , 12 Bytes

c32-p95\32+c

Probieren Sie es online!

Erläuterung

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
Clevere Art, den Unterschied in der Länge der Saiten zu verwalten.
Sanchises

6

Jelly , 15 12 Bytes

z⁶O_32P€‘ịØṖ

Probieren Sie es online!

-3 Danke an Jonathan Allan .


Hinterhältiger Missbrauch von Leerzeichen. ;)
Dennis

@ Tennis Nun, es ist in den Regeln, warum nicht missbrauchen?
Erik der Outgolfer

Ich glaube , Sie 3 Bytes unter Verwendung des argumentlose Atom für druckbare Zeichen speichern kann, ØṖmit z⁶O_32P€‘ịØṖ- Sie würden am besten überprüfen , dass die Arithmetik funktioniert aber.
Jonathan Allan

@ JonathanAllan Natürlich.
Erik der Outgolfer

5

Python 3 , 80 74 71 Bytes

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

Vielen Dank an @shooqie für das Golfen mit 3 Bytes!

Probieren Sie es online!


1
71 wenn Sie (s, t)als Tupel nehmen: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 dank Dennis 'Vorschlag von Shooqies Vorschlag. -2 Bytes dank Zacharýs Vorschlag.

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

Probieren Sie es online!


2
Der gleiche Trick, der für meine Antwort vorgeschlagen wurde:lambda*t:''.join(chr(((ord(i)-32)*(ord(j)-32))%95+32)for i,j in zip(*t))
Dennis

2
Und dasselbe, das ich viel vorgeschlagen habe: ((ord(i)-32)*(ord(j)-32))%95+32=> (ord(i)-32)*(ord(j)-32)%95+32...
Zacharý

o_o Dennis besiegen. +1
Zacharý

1
Ähm, nicht wirklich, ich habe nur zu einem Listenverständnis gewechselt, anstatt es zu verwenden map. Ich war nur etwas spät dran.
Totalhuman

5

Haskell , 60 57 Bytes

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

Probieren Sie es online!

Die erste Zeile ist eine anonyme Funktion mit zwei Argumenten.

Dies ist eine einfache Implementierung des Algorithmus: zipWithNimmt beide Zeichenfolgen und wendet eine gegebene Funktion auf die Zeichenpaare an. Es behandelt das Abschneiden und funktioniert auch für leere Zeichenfolgen. fromEnumund toEnumsind Alternativen zu ordundchr zum Umschalten zwischen Zeichen und ihren ASCII-Werten, für die kein langer Import erforderlich ist.

Edit: -3 Bytes dank Bruce Forte.


Sie können 3Bytes sparen, indem Sie -32diese Klammern herausziehen und speichern (siehe hier) .
21.

5

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

Originalfassung :

#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 dank Bruce Forte
-39 Bytes dank Zacharý

Version 2, inspiriert von den Antworten anderer

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

Wenn die erste Version ein Lambda verwendet, liegt es daran, dass ich die C ++ 11-Funktion std :: async testen wollte, die ich gerade erst gelernt habe, also habe ich sie ohne Grund beibehalten ...

Mehr lesbare 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
Willkommen bei PPCG!
Martin Ender

Willkommen auf der Seite! Vielen Dank für Ihre Antwort, ich weiß das zu schätzen. Ich habe keine Erfahrung mit C ++, aber hier finden Sie einige Tipps. Genieße deine Zeit hier!
21.

Ich bin mir auch ziemlich sicher, dass Sie einfach eine Funktion wie diese einreichen können .
21.

Können Sie die Leerzeichen hier nicht entfernen: #include <string>=> #include<string>und #include <algorithm>=> #include<algorithm>?
Zacharý

Außerdem sollten Sie in der Lage sein, ein Makro zu erstellen, das diesem entspricht, stringund es entsprechend zu verwenden.
Zacharý

3

Dyalog APL, 36 34 33 25 24 Bytes

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

Probieren Sie es online aus (TryAPL)!

Probieren Sie es online (TIO)!

Die Eingabe ist eine Liste von Zeichenfolgen mit nachgestellten Leerzeichen.

So funktioniert das:

{⎕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

Ich habe das Interface von nicht bekommen tryapl.org, also hier ist ein TIO für diejenigen, die es ausprobieren wollen.
21.

Dort habe ich beide reingelegt.
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));}

Probieren Sie es online!

-4 Bytes dank @ Zacharý

-1 Byte durch Verschieben des Inkrements

Verwendet ein Lambda und missbraucht die Tatsache, dass Zeichen grundsätzlich Ints sind.


Kannst du verwenden (l[i]-32)*(n[i]-32)%95+32?
Zacharý

Warum ja, ich kann. Vielen Dank!
Jkelm

1
Sie müssen das vollständig qualifizieren Consoleund Sie können currying verwenden, um ein Byte zu speichern. Kompilieren Sie zu einem Action<string, Action<string>>Like l=>n=>und rufen Sie Like an("word")("string")
TheLethalCoder

2

Mathematica, 114 Bytes

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


Eingang

["public", "toll"]


Gibt es eine Möglichkeit, es online auszuprobieren?
ბიმო

Natürlich, gehen Sie zu sandbox.open.wolframcloud.com/app/objects, fügen Sie den Code ein, fügen Sie die Eingabe am Ende ein, drücken Sie Shift + Enter
J42161217 21.07.17

was "8 Zeichen"?
J42161217

Entschuldigung für die Verwirrung! Die Nachricht "Danke!" Wäre es zu kurz gewesen, um einfach so etwas zu posten, hätte es 8 Zeichen mehr gebraucht.
21.

3
okay....................................
J42161217

2

Gestapelt , 52 Bytes

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

Probieren Sie es online!

Funktion, die zwei Argumente vom Stapel nimmt.

Erläuterung

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

Schauen wir uns den ersten Teil an, vorausgesetzt, die beiden obersten Elemente sind 'split'und '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'))

Dieser Teil führt das Zuschneiden durch.

Dann:

[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 `()`

Dann der letzte Teil:

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

anonyme Funktion; nimmt die Eingabe als zwei Zeichenfolgen auf; Das dritte Argument ist nur, um sicherzustellen, dass dies eine einzeilige Funktion ist, und um einige Bytes zu sparen.

Der unten stehende TIO-Link gibt ein Array mit Einträgen zurück, die mit der ersten Eingabe benannt wurden.

Probieren Sie alle Testfälle aus!




2

05AB1E , 16 15 Bytes

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

Probieren Sie es online!

-1 für Emigna unter Hinweis auf drückt 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

ist ein anderer.


Speichert ein Byte. Schade um die leere Zeichenketteneingabe. Sonst øwürden sich noch ein paar sparen.
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));}

Erläuterung:

Probieren Sie es hier aus.

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

Ich bin sicher, es gibt noch viel zu golfen, aber ich habe gerade keine Zeit.

Probieren Sie es online!

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

Ich denke, (((c-32)*(t.Substring(0,l)[i]-32))%95)+32)kann sein ((c-32)*(t.Substring(0,l)[i]-32)%95+32)(könnte die Eltern dort vermasselt haben ... es sieht aus wie
lisp



1

Python 2 , 95 73 Bytes

  • Danke @ Zacharý für 4 Bytes: unerwünschte Klammern entfernt
lambda x,y:''.join(chr((ord(i)-32)*(ord(j)-32)%95+32)for i,j in zip(x,y))

Probieren Sie es online!


3
Meine Güte, gnädige ... lernen, die Reihenfolge der Operationen zu verwenden! (((ord(x[i])-32)*(ord(y[i])-32))%95)+32=>(ord(x[i])-32)*(ord(y[i])-32)%95+32
Zacharý

1

Kohle , 30 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Ich habe die Berechnung tatsächlich so geschrieben, (32 - ord(q)) * (32 - ord(h))weil sie fortlaufende numerische Literale vermeidet, aber ich denke, ich hätte (ord(q) - ord(" ")) * (ord(h) - ord(" "))stattdessen einfach schreiben können .


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

Probieren Sie es online!

Erläuterung:

@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
Ich denke, Sie kürzen das Ergebnis nicht korrekt auf die Länge der kleineren Zeichenfolge (siehe hier ).
Dada

Du hast recht.
Problem

1

Pip , 19 Bytes

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

Nimmt die Zeichenfolgen als Befehlszeilenargumente. Probieren Sie es online!

Erläuterung

(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

Faktor 45

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

Es ist ein Zitat (Lambda), calldas mit zwei Zeichenfolgen auf dem Stapel die neue Zeichenfolge auf dem Stapel belässt.

Als ein Wort:

: 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

Lösung:

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

Probieren Sie es online!

Beispiel:

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

Erläuterung:

Die Auswertung erfolgt von rechts nach links:

`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); Ich bin mir auch nicht ganz sicher, ob das Ersetzen &&durch &möglicherweise auch in PHP möglich ist, und reduziere es um ein anderes Byte auf 108 .
Kevin Cruijssen

0

JavaScript (ES6), 89 Byte

Javascript und der Fluch der langen Funktionsnamen ...

Mit currying und die Tatsache , dass charCodeAtErträge , NaNwenn sie mit einer ungültigen Position genannt. In der Ausgabe können Nullen nachgestellt sein.

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

Prüfung

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.