Kürzen Sie ein Array

26

Tor:

Erstellen Sie bei einem vorgegebenen Array von Zeichenfolgen abgekürzte Versionen jeder Zeichenfolge.

Spezifikation:

Bei dieser Herausforderung besteht eine Abkürzung aus den ersten N Zeichen einer Zeichenfolge. Für die Zeichenfolge abc: a, ab, und abcsind alle gültigen Abkürzungen, während bc, und acist es nicht.

Bei einem vorgegebenen Array von Zeichenfolgen möchten wir den kürzesten Satz von Abkürzungen finden, sodass Sie anhand der Eingabe und aller Abkürzungen bestimmen können, auf welches Element der Eingabe sich die Abkürzung bezieht.

Beispiel:

Eingang: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]

Wir arbeiten uns durch die Saiten, beginnend mit der ersten.

  • Montag ist nur die Elementzeichenfolge mit einem M, daher ist die kürzestmögliche Abkürzung M.

  • Der Dienstag beginnt mit T, der Donnerstag auch. Dies bedeutet, dass wir die Zeichenfolge versuchen TU. Da damit keine anderen Zeichenfolgen beginnen, verwenden wir TU.

  • Mittwoch ist W, Donnerstag ist Thund Freitag ist F.

Mehr Beispiele:

Input: "one,two,three,four,five,six,seven"
Output: "o,tw,th,fo,fi,si,se"

Input: "red,orange,yellow,green,blue,purple"
Output: "r,o,y,g,b,p"

Input: "a,ab,abc"
Output: Not valid! No abbreviation for `a` that doesn't apply to the other items.

Anmerkungen:

  • Sie geben auf jede vernünftige Weise Daten ein und aus.

  • Sie können davon ausgehen, dass die Eingabe immer ein gültiges Array von Zeichenfolgen ist.

  • Sie können davon ausgehen, dass es anders als im letzten Testfall immer eine Lösung geben wird.

  • Zeichenfolgen bestehen nur aus druckbarem ASCII (oder den druckbaren Zeichen in Ihrer Kodierung)

  • Das ist Codegolf, also gewinnen die wenigsten Bytes!

Julian Lachniet
quelle
Related: 1 , 2 , 3
Sp3000
5
Mögliches Duplikat von Golf Down the PPCG Usernames
Okx
2
Ich denke nicht, dass es ein Duplikat von diesen ist (obwohl sie alle ziemlich ähnlich sind). Tatsächlich denke ich, dass dies wahrscheinlich die beste Herausforderung unter den vier ist. die anderen haben alle Varianten, die sie unnötig komplizieren.
2
Ist Groß- und Kleinschreibung wichtig? In Ihrem Beispiel für einen Wochentag wird insbesondere ein Großbuchstabe Ufür Dienstag, ein Kleinbuchstabe hfür Donnerstag verwendet.
Brian J
1
@Mego Bearbeiten Sie meinen Beitrag nicht, es sei denn, ein Moderator markiert ihn als kein Duplikat
Julian Lachniet

Antworten:

10

Retina , 29 Bytes

!ms`^(.+?)(?!.+^\1)(?<!^\1.+)

Eingabe und Ausgabe sind durch Zeilenvorschub getrennte Listen von Zeichenfolgen.

Probieren Sie es online! (Testsuite mit Kommatrennung zur Vereinfachung.)

Erläuterung

Dies ordnet einfach alle Präfixe einem einzelnen Regex zu und druckt sie aus ( !). mund ssind die üblichen Regex-Modifikatoren, um ^Zeilenanfänge und .Zeilenvorschübe abzugleichen.

^(.+?)      # Match the shortest possible prefix of a line and capture
            # it in group 1.
(?!.+^\1)   # Make sure that this prefix does not show up in a line after
            # the current one.
(?<!^\1.+)  # Make sure that this prefix does not show up in a line before
            # the current one.
Martin Ender
quelle
10

Python 2 , 87-86 Bytes

lambda a:[b[:min(i for i in range(len(b))if sum(s[:i]==b[:i]for s in a)<2)]for b in a]

Probieren Sie es online!

ovs
quelle
lambda a:[[b[:i]for i in range(len(b))if sum(s[:i]==b[:i]for s in a)<2][0]for b in a]für 85 Bytes
Curtis Bechtel
Ersetzen len(b)durch 4**8speichert 2 weitere Bytes, vorausgesetzt, dass Zeichenfolgen nicht länger als 65536 Zeichen sein werden
Curtis Bechtel
8

JavaScript (ES6), 81 78 74 70 Byte

Nimmt Eingaben als ein Array von Zeichenfolgen.

a=>a.map(s=>[...s].reduce((y,c)=>a.some(x=>x!=s&!x.indexOf(y))?y+c:y))

Formatiert und kommentiert

a =>                          // given an array of strings 'a'
  a.map(s =>                  // for each string 's' in 'a':
    [...s].reduce((y, c) =>   //   starting with 'y' = first character of 's',
                              //   for each subsequent character 'c' of 's':
      a.some(x =>             //     if we find a string 'x' in 'a' such that:
        x != s &              //       - 'x' is different from 's'
        !x.indexOf(y)         //       - and 'y' appears at the beginning of 'x'
      ) ?                     //     then:
        y + c                 //       append 'c' to 'y'
      :                       //     else:
        y                     //       keep 'y' unchanged
    )                         //   end of reduce(): returns the correct prefix
  )                           // end of map()

Testfälle

Arnauld
quelle
1
70 auch, aber absolut anders: codegolf.stackexchange.com/a/113270/32091
Qwertiy
+1 für reduce.
Neil
6

Jelly , 14 Bytes

;\w@þ=1Si1⁸ḣð€

Probieren Sie es online!

Wie es funktioniert

;\w@þ=1Si1⁸ḣð€  Monadic link. Argument: A (string array)

            ð   Collect all links to the left into a chain (arity unknown) and
                begin a dyadic chain.
             €  Map the previous chain over A. The current chain is dyadic and the
                mapped one inherits its arity. Thus, the right will be A for all
                invocations, while the left argument will iterate over A.
                For each string s in A, the following happens.
;\                Cumulative reduce by concatenation; yield all prefixes of s.
  w@þ             Window index swapped table; for each string t in A and each
                  prefix p of s, find the index of the substring t in p.
                  The first index is 1; 0 means not found.
     =1           Compare the indices with 1, returning 1 iff t begins with p.
       S          Sum the Booleans across columns, counting the number of strings
                  in A that begin with a given prefix.
        i1        Find the first index of 1, the shortest prefix that is unique
                  across all strings in A.
          ⁸       Head; truncate s to the computed length.
Dennis
quelle
6

Haskell , 48 Bytes

[_]#x=""
a#(c:y)=c:[z|d:z<-a,c==d]#y
f=map=<<(#)

Probieren Sie es online!

  • fist die Hauptfunktion, eine Liste von Strings zu erstellen und a zurückzugeben String. Seine Definition ist eine monadische Abkürzung für f a=map (a#) a.
  • a#xschaut sich die Zeichenkette xund die Liste an aund versucht, das kürzeste Präfix zu finden, in dem xes eindeutig ist a. Wenn aein einzelnes Element vorhanden ist, verwenden Sie einfach die leere Zeichenfolge. Wenn aes sich nicht bereits um ein einzelnes Element handelt, hacken Sie das erste Zeichen von ab x, filtern und hacken Sie die Elemente, adie mit demselben Zeichen beginnen, und wiederholen Sie den Vorgang.
Ørjan Johansen
quelle
4

Mathematica, 64 Bytes

#&@@@StringCases[#,Shortest@x__/;Tr@Boole@StringStartsQ[#,x]<2]&
Martin Ender
quelle
3

Jelly , 14 12 Bytes

ḣ€JṙLḶ$ḟ/€Ḣ€

Probieren Sie es online!

Wie es funktioniert

ḣ€JṙLḶ$ḟ/€Ḣ€  Main link. Argument: A (string array)

  J           Yield the 1-based indices of A, i.e., [1, ..., len(A)].
ḣ€            Head each; for each string s in A, take the first 1, ..., and len(A) 
              characters. This builds the 2D array of prefixes of all strings in A.
    LḶ$       Length-unlength; yield [0, ..., len(A)-1].
   ṙ          Rotate the 2D array 0, ..., and len(A)-1 units to the left.
       ḟ/€    Reduce filterfalse each; for each rotation, remove all prefixes from
              the first set that also occur in later sets.
          Ḣ€  Head each; for each rotation, keep only the shortest unique prefix.
Dennis
quelle
Ich frage mich nur, warum hast du hier 2 Antworten? Ich mag sie beide, aber ich frage mich nur, warum du hier zwei Gelee-Antworten hast. :)
HyperNeutrino
Wenn ich zwei ähnlich konkurrierende, aber ausreichend unterschiedliche Ansätze habe, poste ich sie normalerweise in separaten Antworten.
Dennis
Guter Punkt. Ja, ich habe mich nur gefragt. :) Das ist eine gute Idee; Normalerweise habe ich nicht mehr als einen Ansatz: P
HyperNeutrino
2

C ++ 11 (MinGW), 198 Bytes

#import<list>
#import<iostream>
f(std::list<std::string>l){int i,m;for(auto s:l){for(i=0,m=1;++i<s.length();)for(auto t:l)if(t!=s&&t.substr(0,i)==s.substr(0,i))m=i+1;std::cout<<s.substr(0,m)<<" ";}}

Rufen Sie an mit:

int main()
{
    f({"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"});
}

Das Hinzufügen eines voidBezeichners vor der Funktion sollte dazu führen, dass sie auch auf anderen Compilern kompiliert wird, wodurch die Länge um 5 Byte erhöht wird.

Steadybox
quelle
Es sollte sein void f..., es does't Arbeit sonst ... + 5 Bytes, leider. Funktionen, soweit ich weiß, brauchen Typspezifizierer in C ++
Mr. Xcoder
Ansonsten ein hervorragender Ansatz! Golfen in C / C ++ kann schmerzhaft sein
Mr. Xcoder
@ Mr.Xcoder Kompiliert auf dem MinGW-Compiler, den ich verwende. Es ist also entweder eine Compiler-Erweiterung oder ein undefiniertes Verhalten.
Steadybox
Ich denke, es geht um die Compiler-Erweiterung, auf GCC funktioniert es nicht ...
Mr. Xcoder
1
Solange es eine Umgebung gibt, in der der Code funktioniert, ist er gültig
undergroundmonorail
2

Javascript ES6, 70 Zeichen

s=>(s+'#'+s).replace(/(\w+?)(\w*)(?=(\W(?!\1(?!\2))\w+)+$)|#.+/g,"$1")

f=s=>(s+'#'+s).replace(/(\w+?)(\w*)(?=(\W(?!\1(?!\2))\w+)+$)|#.+/g,"$1")

console.log(f("one,two,three,four,five,six,seven")==="o,tw,th,fo,fi,si,se")
console.log(f("red,orange,yellow,green,blue,purple")==="r,o,y,g,b,p")
console.log(f("one,two,three,four,five,six,seven".split`,`)==="o,tw,th,fo,fi,si,se")
console.log(f("red,orange,yellow,green,blue,purple".split`,`)==="r,o,y,g,b,p")

Qwertiy
quelle
2

PHP, 131 120 119 118 Bytes

Danke @ Jörg für preg_grep.

for(;a&$s=$argv[++$k];$i=+$t=!print"$t
")for(;a&$s[$i]&&1<count(preg_grep("(^".preg_quote($t.=$s[$i++]).")",$argv)););

Nimmt Eingaben von Befehlszeilenargumenten entgegen. druckt die Ergebnisse jeweils eine Zeile.
Laufen Sie mit -nroder versuchen Sie es online .

  • kann fehlschlagen, wenn die Eingabe etwas enthält, das mit beginnt -.
    +15 Bytes zum Reparieren: Ersetzen Sie die Sekunde $argvdurch array_slice($argv,1).
  • gibt Warnungen in PHP 7.1 aus; Ersetzen Sie a&durch ""<(+1 Byte), um den Fehler zu beheben.
  • -12 Bytes , wenn der Eingang keine regex Sonderzeichen enthält:
    Legen Sie &($t.=$c)vor &&und ersetzen ". preg_quote($t.=$c)."mit $t.

Nervenzusammenbruch

for(;a&$s=$argv[++$k];      # loop $s through arguments
    $i=+$t=!                # 3. reset $i and $t to empty
    print"$t\n")            # 2. print abbreviation
    for(;a&($c=$s[$i++])    # 1. loop $c through characters
        &&1<count(              # 3. if count==1, break loop
            preg_grep("(^"      # 2. find matching arguments
                . preg_quote(
                $t.=$c          # 1. append $c to abbreviation
            ).")",$argv)
        );
    );

Nicht-Regex-Version, 131 130 Bytes

for($a=$argv;a&$s=$a[++$k];$i=+$t=!print"$t
")for($n=1;$n&&a&$c=$s[$i++];)for($n=$m=1,$t.=$c;a&$u=$a[$m++];)$n-=0===strpos($u,$t);

Ersetzen Sie das erste und das letzte a&mit ""<(+2 Bytes), um PHP 7.1 zu reparieren.

Nervenzusammenbruch

for($a=$argv;a&$s=$a[++$k];     # loop through arguments
    $i=+$t=!print"$t\n")            # 2. print abbreviation, reset $i and $t to empty
    for($n=1;$n&&a&$c=$s[$i++];)    # 1. loop through characters while $n<>0
        for($n=$m=1,                    # reset $n and $m to 1
            $t.=$c;                     # append current character to prefix
            a&$u=$a[$m++];              # loop through arguments:
        )$n-=0===strpos($u,$t);         # -$n = number of matching strings -1

ganz uninteressant hinweis:
strstr($u,$t)==$uund 0===strpos($u,$t)haben die gleiche länge und das gleiche ergebnis.

Titus
quelle
Verwenden Sie 0x0Astattdessen ein echtes Newline-Zeichen ( ) \n, um ein Byte zu sparen.
Blackhole
@Blackhole Danke; Das habe ich diesmal vergessen.
Titus
1

PHP, 127 Bytes

funktioniert nicht mit ungültigen Arrays

<?foreach($a=$_GET as$k=>$v)for($i=0,$c=2,$s="";$c>1;$r[$k]=$s)$c=count(preg_grep("_^".($s.=$v[$i++])._,$a));echo join(",",$r);

PHP, 132 Bytes

<?foreach($a=$_GET as$v)for($i=0,$s="";a&$v[$i];)if(count(preg_grep("_^".($s.=$v[$i++])._,$a))==1){$r[]=$s;break;}echo join(",",$r);

Online Version

151 Bytes unterstützt Sonderzeichen

<?foreach($a=$_GET as$v)for($i=0,$s="";a&$v[$i];)if(count(preg_grep("_^".preg_quote($s=substr($v,0,++$i),_)._,$a))==1){$r[]=$s;break;}echo join(",",$r);

PHP, 140 Bytes

<?foreach($a=$_GET as$k=>$v)for($i=0;a&$v[$i];)if(count(preg_grep("#^".($s=substr($v,0,++$i))."#",$a))==1){$r[]=$s;break;}echo join(",",$r);
Jörg Hülsermann
quelle
Dies schlägt fehl, wenn die Eingabe reguläre Sonderzeichen enthält. Ich hätte 113 Bytes anstatt 131, wenn nicht.
Titus
@Titus In diesem Fall könnte ich ein preg_quoteMake nur 10 Bytes mehr hinzufügen
Jörg Hülsermann
Es wird auch fehlschlagen, wenn die Eingabe enthält 0. Mit können Sie aber ein Byte sparen $i=+$s="".
Titus
und Sie können das count()-count()Zeug entfernen : Eingabe ist garantiert gültig (-21 Bytes). Ich denke, ich könnte das beheben und auf 120 Bytes reduzieren. $_GETwar eine gute idee!
Titus
@Titus Ich habe nicht bemerkt, dass nur gültige Arrays erlaubt sind. Ja, es würde scheitern, wenn die Zeichenfolge eine Null enthalten würde, aber dies war die
Jörg Hülsermann,
0

Clojure, 118 Bytes

#(reduce(partial map(fn[a b](or a b)))(for[i(range 1e2)S[(for[c %](take i c))]](for[s S](if(=((frequencies S)s)1)s))))

Dies funktioniert bei Präfixen bis zu einer Länge von, 1e2aber die gleiche Byteanzahl kann bis zu unterstützen 1e9. iLoops Längen von Präfixen, Sist die Folge von Teilzeichenfolgen der Länge i. Der letzte forersetzt die Unterzeichenfolgen, nildie öfter als einmal vorkommen. Die Reduzierung behält den ersten Nicht-Null-Wert für jede Zeichenfolge bei. Schade, dass ores sich nicht um eine Funktion handelt, also musste ich sie umbrechen.

Dies gibt tatsächlich Listen mit Listen von Zeichen wie ((\M) (\T \u) (\W) (\T \h) (\F)), aber ich denke, es ist akzeptabel. Clojure ist ziemlich ausführlich mit Streichern und subswürde StringIndexOutOfBoundsExceptionanders werfen take.

Vollständige Beispiele:

(def f #(reduce(partial map(fn[a b](or a b)))(for[i(range 1e2)S[(for[c %](take i c))]](for[s S](if(=((frequencies S)s)1)s)))))

(f ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"])
(f (re-seq #"[^,]+" "one,two,three,four,five,six,seven"))
(f (re-seq #"[^,]+" "red,orange,yellow,green,blue,purple"))
NikoNyrh
quelle
0

SQL (PostgreSQL 9.4-Version), 219 Byte

Nun zur längsten Antwort :) Ich glaube nicht, dass dies Java schlagen könnte. Ich werde versuchen, ein paar mehr davon abzurasieren. Ich hoffe, eine der verschachtelten Abfragen loszuwerden, aber ich mag meine Chancen nicht.
Dies setzt voraus, dass es eine Tabelle gibt, die die zu bearbeitenden Zeichenfolgen enthält. Da dies SQL ist, kann nicht garantiert werden, dass die Reihenfolge der Rückgabe mit der Tabellenreihenfolge übereinstimmt. In diesem Fall ist dies unwahrscheinlich. Wenn dies ein Problem ist, werde ich löschen.

SELECT R FROM(SELECT*,RANK()OVER(PARTITION BY A ORDER BY C,N)Z FROM(SELECT*,SUM(1)OVER(PARTITION BY R)C FROM(SELECT*FROM A JOIN LATERAL(select left(A,n)R,N FROM generate_series(1,length(A))S(n))L ON 1=1)X)Y)Z WHERE Z=1

SQL Fiddle
Erklärung

  SELECT *
  FROM A 
    JOIN LATERAL(SELECT LEFT(A,n)R,N 
    FROM generate_series(1,length(A))S(n))L ON 1=1

Die innerste Abfrage verwendet generate_seriesund einen LATERALJoin, um Zeilen für die Zeichenfolge zu erstellen, die in zunehmende Längen unterteilt sind, sodass aus "Eins" "O", "Ein", "Eins" wird. Die Anzahl der Zeichen in der Rückgabe wird ebenfalls beibehalten.

SELECT 
  *,
  SUM(1)OVER(PARTITION BY R)C
FROM ( ... )X

Dann addieren wir die Anzahl der Datensätze, die das gleiche Ergebnis haben. Zum Beispiel 'f' von vier und fünf hat 2, aber 'fo' und 'fi' haben jeweils eine. Die OVERAnweisung in SQL kann sehr mächtig sein. COUNT(*)wäre der übliche weg, SUM(1)ergibt aber das gleiche ergebnis.

SELECT 
  *,
  RANK()OVER(PARTITION BY A ORDER BY C,N)Z
FROM ( ... )Y

Dann ordnen wir die Ergebnisse für jede Eingabe basierend auf den geringsten Wiederholungen und Zeichen. ROW_NUMBERwürde auch hier funktionieren, ist aber länger.

SELECT R FROM ( ... )Z WHERE Z=1;

Schließlich wählen wir die niedrigste Rangnummer für jedes Wort.

MickyT
quelle
0

Pure Bash , 146 Bytes

for i in $@;{ K=1;U=${i::1};((M++));L=;while [[ `for v in $@;{ ((L++));(($L!=$M))&&echo ${v::K}||:;}` =~ $U ]];do U=${i::K};((K++));done;echo $U;}

Probieren Sie es online!

R. Kap
quelle
0

APL (Dyalog) , 27 Bytes

{⍵↑¨⍨1⍳⍨¨↓+/(↑,⍵)∘.(⊃⍷)⍵}

Probieren Sie es online!

{ eine anonyme Funktion, wobei ⍵ das Argument darstellt ...

∘.( eine Funktionstabelle, in der sich die Funktion befindet

   das erste Element von

   die Boolesche Liste "linkes Argument beginnt hier im rechten Argument?"

) Wo die richtigen Argumente sind

 die Argumente

( und das linke Argument ist

   eine Tabelle mit Zeilen bestehend aus

  ,/ Präfixe von

  ¨ jeder von

   die Argumente

+/ Summe über (zählt, wie viele Argumente mit diesem Präfix übereinstimmen)

 Tabelle in Zeilen aufteilen

⍳⍨¨ Finden Sie in jedem den Ort des ersten

1 eins (dh das erste Präfix, das nur ein Argument anführt)

↑¨⍨ Nimmt für jede Position so viele Zeichen aus dem entsprechenden Element von

 das Argument

} Ende der anonymen Funktion

Adam
quelle
0

PowerShell, 151 139 Byte

$x,$w=@(),$args[0];$w|%{$k=$_;$a='';foreach($l in [char[]]$k){$a+=$l;if($a-notin$x-and!($w|?{$_-ne$k-and$_-like"$a*"})){$x+=$a;break;}}};$x

Interessiert, ob es einen besseren Weg gibt, dies zu tun. Musste a foreach(über a |%) verwenden, um eine breakin der verschachtelten Schleife ausführen zu können, ohne sie zu kennzeichnen.

Bearbeiten: 2 Golfplätze von AdmBorkBork

Tor
quelle
1
Ich habe den Code nicht direkt durchgearbeitet, aber Sie könnten doch sicher -notinanstelle von -not$x.contains($a)und !($w...anstelle von ein -not($w...paar Bytes sparen, ja?
AdmBorkBork
0

APL, 26 Bytes

{⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}

Erläuterung:

  • ↓↑⍵: Pad jede Zeichenfolge in die Länge der längsten Zeichenfolge
  • ∘.(... )⍨: Finden Sie für jedes mögliche Paar von Zeichenfolgen das gemeinsame Präfix:
    • : Array-Ungleichung
    • : und
    • =: Itemweise Gleichheit
    • ∧\: and-scan (nur die führenden Übereinstimmungen behalten)
  • +/¨: summiere jeden Vektor in der Tabelle und gebe die Länge der gemeinsamen Präfixe an
  • ⌈/: finde den Maximalwert in jeder Spalte
  • 1+: fügen Sie eine hinzu und geben Sie die Anzahl der Zeichen an, die erforderlich sind, um jede Zeichenfolge eindeutig zu halten
  • ⍵↑¨⍨: nimm so viele Zeichen aus jeder Zeichenkette

Prüfung:

      {⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}'Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday'
┌─┬──┬─┬──┬─┐
│M│Tu│W│Th│F│
└─┴──┴─┴──┴─┘
      {⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}'one' 'two' 'three' 'four' 'five' 'six' 'seven'
┌─┬──┬──┬──┬──┬──┬──┐
│o│tw│th│fo│fi│si│se│
└─┴──┴──┴──┴──┴──┴──┘
      {⍵↑¨⍨1+⌈/+/¨∘.(∧\=∧≢)⍨↓↑⍵}'red' 'orange' 'yellow' 'green' 'blue' 'purple'
┌─┬─┬─┬─┬─┬─┐
│r│o│y│g│b│p│
└─┴─┴─┴─┴─┴─┘
Marinus
quelle
0

Q, 93 Bytes

{n:1;{$[any e:(,/)1<{(+/)i like x}each i:z#'x;[z+:1;y:?[e;z#'x;i];.z.s[x;y;z]];y]}[x;n#'x;n]}

Wird rekursiv gelöst, nimmt den String als Eingabe und erhält bei jeder Rekursion die ersten n Elemente jedes Strings. Wenn eines dieser Elemente nicht eindeutig ist, werden sie durch die ersten n + 1 Elemente ersetzt.

Daniel Plainview
quelle