Abbrevia un array


26

Obbiettivo:

Data una matrice di stringhe, creare versioni abbreviate di ogni stringa.

Specifica:

Per questa sfida, un'abbreviazione è i primi N caratteri di una stringa. Per la stringa abc: a, ab, e abcsono tutte le abbreviazioni valide, mentre bc, e acnon lo sono.

Dato un array di stringhe, vogliamo trovare il set più breve di abbreviazioni, in modo tale che, dato l'input e l'eventuale abbreviazione, sia possibile determinare a quale elemento dell'input si riferiva l'abbreviazione.

Esempio:

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

Lavoriamo attraverso le stringhe iniziando dal primo.

  • Lunedì è solo la stringa dell'articolo con un M, quindi l'abbreviazione più breve possibile è M.

  • Il martedì inizia con T, ma anche giovedì. Questo significa che proviamo la stringa TU. Poiché nessun'altra stringa inizia con quella, usiamo TU.

  • Mercoledì è W, giovedì è The venerdì è F.

Altri esempi:

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.

Gli appunti:

  • Fai input e output in modo ragionevole.

  • Puoi presumere che l'input sarà sempre un array valido di stringhe.

  • Puoi presumere che ci sarà sempre una soluzione, a differenza dell'ultimo caso di test.

  • Le stringhe consistono solo di ASCII stampabili (o dei caratteri stampabili nella codifica)

  • Questo è il codice golf, quindi vincono meno byte!


Correlati: 1 , 2 , 3
Sp3000

5
Possibile duplicato di Golf Down the PPCG Usernames
Okx

2
Non penso sia un duplicato di nessuno di questi (anche se sono tutti abbastanza simili). In realtà, penso che questa sia probabilmente la migliore sfida tra i quattro; gli altri hanno varianti che le rendono inutilmente complicate.

2
Il caso è importante? In particolare, l'esempio del giorno della settimana utilizza un capitale Uper martedì, ma un minuscolo hper giovedì.
Brian J,

1
@Mego Non modificare il mio post a meno che un moderatore non lo segnerà come un duplicato
Julian Lachniet

Risposte:


10

Retina , 29 byte

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

Input e output sono elenchi di stringhe separati da avanzamento riga.

Provalo online! (Test suite con separazione delle virgole per comodità.)

Spiegazione

Questo semplicemente abbina tutti i prefissi con una sola regex e li stampa ( !). me ssono i soliti modificatori regex per creare l' ^inizio della linea di corrispondenza e l'alimentazione della linea di .corrispondenza.

^(.+?)      # 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.

10

Python 2 , 87 86 byte

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]

Provalo online!


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]per 85 byte
Curtis Bechtel,

la sostituzione len(b)con 4**8salva altri 2 byte, supponendo che le stringhe non siano più lunghe di 65536 caratteri
Curtis Bechtel,

8

JavaScript (ES6), 81 78 74 70 byte

Accetta input come una matrice di stringhe.

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

Formattato e commentato

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

Casi test


1
70, ma assolutamente altro: codegolf.stackexchange.com/a/113270/32091
Qwertiy

+1 per reduce.
Neil

6

Gelatina , 14 byte

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

Provalo online!

Come funziona

;\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.

6

Haskell , 48 byte

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

Provalo online!

  • fè la funzione principale, prendendo un elenco di se Stringrestituendo a String. La sua definizione è una scorciatoia monadica per f a=map (a#) a.
  • a#xesamina la stringa xe l'elenco ae cerca di trovare il prefisso più breve di xquello in cui è univoco a. Se aha un singolo elemento, basta usare la stringa vuota. Se anon è già un singolo elemento, tagliare il primo carattere di x, filtrare e tagliare gli elementi di apartenza con lo stesso carattere, quindi ricorrere.

4

Mathematica, 64 byte

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

3

Gelatina , 14 12 byte

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

Provalo online!

Come funziona

ḣ€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.

Mi chiedo solo, perché hai 2 risposte qui? Mi piacciono entrambi ma mi chiedo solo perché hai due risposte Jelly qui. :)
HyperNeutrino

Se ho due approcci altrettanto competitivi ma approcci sufficientemente diversi, di solito li inserisco in risposte separate.
Dennis

Buon punto. Sì, mi stavo solo chiedendo. :) Questa è una buona idea; Di solito non ho più di un approccio: P
HyperNeutrino

2

C ++ 11 (MinGW), 198 byte

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

Chiama con:

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

L'aggiunta voiddell'identificatore prima della funzione dovrebbe farlo compilare anche su altri compilatori, aggiungendo quindi 5 byte alla lunghezza.


Dovrebbe essere void f..., non funziona altrimenti ... + 5 byte, sfortunatamente. Le funzioni, per quanto ne so, hanno bisogno di
identificatori di

Inoltre, un approccio eccezionale! Giocare a golf in C / C ++ può essere doloroso
Mr. Xcoder

@ Mr.Xcoder Si compila sul compilatore MinGW che sto usando, però. Quindi è un'estensione del compilatore o un comportamento indefinito.
Steadybox

Penso che riguardi l'estensione del compilatore, su GCC non funziona ...
Mr. Xcoder

1
Finché esiste un ambiente in cui il codice funziona, è valido
undergroundmonorail

2

Javascript ES6, 70 caratteri

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


2

PHP, 131 120 119 118 byte

Grazie @ Jörg per 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)););

accetta input dagli argomenti della riga di comando; stampa i risultati una riga ciascuno.
Corri con -nro provalo online .

  • potrebbe non riuscire se l'input contiene qualcosa che inizia con -.
    +15 byte da correggere: sostituire il secondo $argvcon array_slice($argv,1).
  • genera avvisi in PHP 7.1; sostituire a&con ""<(+1 byte) per risolvere.
  • -12 byte se l'input non contiene caratteri speciali regex:
    inserire &($t.=$c)prima &&e sostituire ". preg_quote($t.=$c)."con $t.

abbattersi

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

versione non regex, 131 130 byte

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

Sostituisci il primo e l'ultimo a&con ""<(+2 byte) da correggere per PHP 7.1.

abbattersi

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

nota completamente poco interessante:
strstr($u,$t)==$ue 0===strpos($u,$t)hanno la stessa lunghezza e lo stesso risultato.


Usa un carattere di nuova riga reale ( 0x0A) invece di \n, salverà un byte;).
Blackhole,

@Blackhole Grazie; Me ne sono dimenticato questa volta.
Tito

1

PHP, 127 byte

non funziona con array non validi

<?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 byte

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

Versione online

151 byte supporta caratteri speciali

<?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 byte

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

Ciò fallirà se l'input contiene caratteri speciali regex. Avrei 113 byte invece di 131 in caso contrario.
Tito

@Titus In questo caso potrei aggiungere un preg_quoteMake solo 10 byte in più
Jörg Hülsermann

Fallirà anche se l'input contiene 0. Ma puoi salvare un byte con $i=+$s="".
Tito

e puoi rimuovere il count()-count()materiale: l'input è garantito per essere valido (-21 byte). Penso che potrei risolvere e golf questo fino a 120 byte. $_GETè stata una buona idea!
Tito

@Titus Non ho capito che sono ammessi solo array validi. Sì, fallirebbe se la stringa contenesse uno zero, ma da ciò è nata un'idea
Jörg Hülsermann

0

Clojure, 118 byte

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

Funziona con prefissi fino alla lunghezza di 1e2ma lo stesso conteggio byte può supportare fino a 1e9. iloop lunghezze di prefissi, Sè la sequenza di sottostringhe di lunghezza i. L'ultimo forsostituisce quelle sottostringhe con nilcui si verificano più frequentemente di una volta. La riduzione mantiene il primo valore diverso da zero per ogni stringa, peccato che ornon sia una funzione, quindi ho dovuto racchiuderlo.

Questo in realtà restituisce elenchi di elenchi di personaggi come ((\M) (\T \u) (\W) (\T \h) (\F)), ma immagino sia accettabile. Clojure è piuttosto prolisso con le stringhe e subsgetterebbe StringIndexOutOfBoundsExceptiondiversamente take.

Esempi completi:

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

0

SQL (sapore PostgreSQL 9.4), 219 byte

Ora per la risposta più lunga :) Non credo che questo potrebbe persino battere Java. Proverò a radunarmi un po 'di più. Spero di sbarazzarmi di una delle domande nidificate, ma non mi piacciono le mie possibilità.
Ciò presuppone che esista una tabella che contiene le stringhe su cui lavorare. Poiché si tratta di SQL, l'ordine del ritorno non è garantito essere uguale all'ordine della tabella e in questo caso è improbabile. Se questo è un problema, lo eliminerò.

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


Spiegazione del violino SQL

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

La query più interna utilizza generate_seriese un LATERALjoin per creare righe per la stringa divisa in lunghezze crescenti, quindi 'one' diventa 'o', 'on', 'one'. Viene inoltre mantenuto il numero di caratteri nel ritorno.

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

Quindi aggiungiamo il numero di record che hanno lo stesso risultato. Ad esempio 'f' da quattro e cinque ha 2, ma 'fo' e 'fi' ne hanno uno ciascuno. L' OVERistruzione in SQL può essere abbastanza potente. COUNT(*)sarebbe il solito modo, ma SUM(1)dà lo stesso risultato.

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

Quindi classifichiamo i risultati per ciascun input in base al numero minimo di ripetizioni e caratteri. ROW_NUMBERfunzionerebbe anche qui, ma è più lungo.

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

Infine selezioniamo il numero di rango più basso per ogni parola.


0

Pure Bash , 146 byte

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

Provalo online!


0

APL (Dyalog) , 27 byte

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

Provalo online!

{ una funzione anonima, dove ⍵ rappresenta l'argomento ...

∘.( una tabella delle funzioni in cui si trova la funzione

   il primo elemento di

   l'elenco booleano "l'argomento di sinistra inizia qui nell'argomento di destra?"

) dove sono gli argomenti giusti

 le argomentazioni

( e l'argomento di sinistra è

   una tabella con righe costituite da

  ,/ prefissi di

  ¨ ciascuna di

   gli argomenti

+/ somma attraverso (conta quanti argomenti si definiscono con questo prefisso)

 dividere la tabella in un elenco di righe

⍳⍨¨ in ognuno, trova la posizione del primo

1 uno (ovvero il primo prefisso che contiene solo un argomento)

↑¨⍨ per ogni posizione, prende così tanti caratteri dall'elemento corrispondente di

 l'argomento

} fine della funzione anonima


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

Interessato se c'è un modo migliore per farlo. Ho dovuto usare un foreach(sopra a |%) per poter eseguire un breakciclo nidificato senza etichettarlo.

Modifica: 2 golf da AdmBorkBork


1
Non ho esaminato direttamente il codice, ma sicuramente potresti usare -notininvece di -not$x.contains($a)e !($w...invece di -not($w...salvare alcuni byte, sì?
AdmBorkBork

0

APL, 26 byte

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

Spiegazione:

  • ↓↑⍵: inserisce ciascuna stringa in modo che corrisponda alla lunghezza della stringa più lunga
  • ∘.(... )⍨: per ogni possibile coppia di stringhe, trova il prefisso condiviso:
    • : disuguaglianza di array
    • : e
    • =: uguaglianza per oggetto
    • ∧\: and-scan (mantieni solo le partite principali)
  • +/¨: somma ogni vettore nella tabella, fornendo la lunghezza dei prefissi condivisi
  • ⌈/: trova il valore massimo in ogni colonna
  • 1+: aggiungine uno, fornendo la quantità di caratteri necessari per mantenere unica ogni stringa
  • ⍵↑¨⍨: prende tanti caratteri da ogni stringa

Test:

      {⍵↑¨⍨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│
└─┴─┴─┴─┴─┴─┘

0

Q, 93 byte

{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]}

Risolto in modo ricorsivo, prende la stringa come input, ottiene i primi n elementi di ogni stringa ad ogni ricorsione. Se uno di questi elementi non è univoco, li sostituisce con i primi n + 1 elementi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.