L'alfabeto di mia figlia


65

L'altro giorno stavamo scrivendo frasi con mia figlia con una lettera con il magnete del frigorifero. Sebbene siamo stati in grado di creare alcuni ( I love cat), non avevamo abbastanza lettere per creare gli altri ( I love you too) a causa di una quantità insufficiente di lettere o(4)

Ho poi scoperto che mentre un set includeva 3 elettere aveva solo 2 olettere. Probabilmente ispirato da http://en.wikipedia.org/wiki/Letter_frequency, ciò non rifletterebbe ancora la situazione reale "sul frigorifero".

Problema

Dato il file di testo in cui ogni riga contiene una "frase di esempio" si vorrebbe scrivere sul frigorifero, proporre un set di alfabeto con un numero minimo di lettere ma comunque sufficiente per scrivere ogni frase individualmente.

Nota: ignora i casi, tutte le lettere del magnete sono comunque maiuscole.

Ingresso

Il file contiene frasi separate da una nuova riga:

hello
i love cat
i love dog
i love mommy
mommy loves daddy

Produzione

Fornisci di nuovo un elenco ordinato di lettere, in cui ogni lettera appare solo tante volte per essere sufficiente per scrivere qualsiasi frase:

acdddeghillmmmoostvyy

(grazie, isaacg!)

Vincitore

Implementazione più breve (codice)

AGGIORNATO: Test

Ho creato un test aggiuntivo e ho provato con varie risposte qui:

https://gist.github.com/romaninsh/11159751


2
Dovrebbe esserci una lettera vnell'output;)
Antonio Ragagnin,

40
Ci è permesso / richiesto di sostituire un capovolto con Mun W, o lateralmente Ncon un Z? ;-)
Ilmari Karonen,

4
Fondamentalmente puoi costruire qualsiasi lettera usando Is.
Swish,

7
Più seriamente, quando dici "ignora casi", vuoi dire che possiamo supporre che l'input sia già tutto nello stesso caso o che dobbiamo convertirlo tutto nello stesso caso? Inoltre, è corretto che l'output includa alcuni spazi iniziali?
Ilmari Karonen,

3
@Doorknob:_\¯
Ilmari Karonen,

Risposte:


18

GolfScript, 28/34 caratteri

n/:a{|}*{a{.[2$]--}%*$-1=}%$

Il programma di 28 caratteri sopra presuppone che tutte le lettere di input siano nello stesso caso. Se ciò non è necessariamente così, possiamo forzarli in maiuscolo anticipando {95&}%il codice, per un totale di 34 caratteri:

{95&}%n/:a{|}*{a{.[2$]--}%*$-1=}%$

Appunti:

  • Per un corretto funzionamento, l'input deve includere almeno una nuova riga. Questo sarà vero per i normali file di testo con nuove righe alla fine di ogni riga, ma potrebbe non essere vero se l'input è costituito da una sola riga senza newline finali. Questo potrebbe essere risolto al costo di due caratteri aggiuntivi, anticipando n+il codice.

  • Le maiuscole utilizzate nella versione a 34 caratteri sono davvero rozze: associa lettere ASCII minuscole ai loro equivalenti maiuscoli (e spazi a NULs), ma crea un pasticcio completo di numeri e la maggior parte della punteggiatura. Suppongo che l'input non includerà tali caratteri.

  • La versione di 28 caratteri tratta tutti i caratteri di input (eccetto newline e NULs) allo stesso modo. In particolare, se l'input contiene spazi, alcuni appariranno anche nell'output; convenientemente, ordineranno prima di qualsiasi altro carattere ASCII stampabile. La versione a 34 caratteri, tuttavia, ignora gli spazi (perché si scopre che posso farlo senza costarmi alcun carattere aggiuntivo).

Spiegazione:

  • Il {95&}%prefisso opzionale rende maiuscolo l'input azzerando il sesto bit del codice ASCII di ciascun byte di input ( ). Questo mappa le lettere ASCII minuscole in maiuscolo, gli spazi in byte nulli e lascia invariate le nuove righe.95 = 64 + 31 = 10111112

  • n/divide l'input a newline e :aassegna l'array risultante alla variabile a. Quindi {|}*calcola l'unione set delle stringhe nell'array, che (supponendo che l'array abbia almeno due elementi) produce una stringa contenente tutti i caratteri univoci (non newline) nell'input.

  • Il { }%ciclo seguente scorre poi su ciascuno di questi personaggi unici. All'interno del corpo del ciclo, il ciclo interno a{.[2$]--}%scorre sopra le stringhe dell'array a, rimuovendo da ogni stringa tutti i caratteri non uguali a quello su cui il ciclo esterno sta ripetendo.

    Il ciclo interno lascia il codice ASCII del carattere corrente nello stack, sotto l'array filtrato. Ne facciamo uso ripetendo l'array filtrato tutte le volte indicato dal codice ASCII ( *) prima di ordinarlo ( $) e prendere l'ultimo elemento ( -1=). In effetti, questo produce la stringa più lunga nell'array filtrato (poiché sono tutti composti da ripetizioni dello stesso carattere, l'ordinamento lessicografico li ordina solo per lunghezza), tranne se il carattere ha il codice ASCII zero, nel qual caso non produce nulla.

  • Infine, $alla fine ordina l'output in ordine alfabetico.


3
Sorprendente. TODO: Impara GolfScript!
DLosc,

1
Si può anche ridurre a 26: n/:a{|}*{{{=}+,}+a%$-1=}%$.
Howard,

13

J - 37 char

Legge da stdin, output su console.

dlb#&a.>./+/"2=/&a.tolower;._2[1!:1]3

1!:1]3è la chiamata a stdin. tolower;._2esegue il doppio dovere suddividendo le linee e rendendole minuscole contemporaneamente. Quindi contiamo quante volte compare un carattere in ogni riga +/"2=/&a.e prendiamo il massimo in senso puntuale su tutte le righe con >./.

Infine, estraiamo molti di ogni personaggio dall'alfabeto con #&a.. Ciò include gli spazi, tutti presenti nella parte anteriore a causa del loro basso valore ASCII, quindi eliminiamo solo gli spazi iniziali con dlb.


12

JavaScript (ECMAScript 6) - 148 139 135 caratteri

Versione 2:

Aggiornato per usare la comprensione dell'array:

[a[i][0]for(i in a=[].concat(...s.split('\n').map(x=>x.split(/ */).sort().map((x,i,a)=>x+(a[i-1]==x?++j:j=0)))).sort())if(a[i-1]<a[i])]

Versione 1:

[].concat(...s.split('\n').map(x=>x.split(/ */).sort().map((x,i,a)=>x+(a[i-1]==x?++j:j=0)))).sort().filter((x,i,a)=>a[i-1]!=x).map(x=>x[0])

Suppone che:

  • La stringa di input è nella variabile s;
  • Possiamo ignorare il caso dell'input (come specificato dalla domanda - cioè è tutto in maiuscolo o minuscolo);
  • L'output è un array di caratteri (che è quasi il più vicino possibile a JavaScript per il requisito OP di un elenco di caratteri); e
  • L'output deve essere visualizzato sulla console.

Con commenti:

var l = s.split('\n')             // split the input up into sentences
         .map(x=>x.split(/ */)   // split each sentence up into letters ignoring any
                                  // whitespace
                  .sort()         // sort the letters in each sentence alphabetically
                  .map((x,i,a)=>x+(a[i-1]==x?++j:j=0)))
                                  // append the frequency of previously occurring identical
                                  // letters in the same sentence to each letter.
                                  // I.e. "HELLO WORLD" =>
                                  // ["D0","E0","H0","L0","L1","L2","O0","O1","R0","W0"]
[].concat(...l)                   // Flatten the array of arrays of letters+frequencies
                                  // into a single array.
  .sort()                         // Sort all the letters and appended frequencies
                                  // alphabetically.
  .filter((x,i,a)=>a[i-1]!=x)     // Remove duplicates and return the sorted
  .map(x=>x[0])                   // Get the first letter of each entry (removing the
                                  // frequencies) and return the array.

Se lo desidera:

  • Restituiscilo come una stringa quindi aggiungi .join('')alla fine;
  • Accetta input da un utente, quindi sostituisci la svariabile con prompt(); o
  • Scrivilo come una funzione, fquindi aggiungi f=s=>all'inizio.

In esecuzione:

s="HELLO\nI LOVE CAT\nI LOVE DOG\nI LOVE MOMMY\nMOMMY LOVE DADDY";
[].concat(...s.split('\n').map(x=>x.split(/ */).sort().map((x,i,a)=>x+(a[i-1]==x?++j:j=0)))).sort().filter((x,i,a)=>a[i-1]!=x).map(x=>x[0])

Fornisce l'output:

["A","C","D","D","D","E","G","H","I","L","L","M","M","M","O","O","T","V","Y","Y"]

1
Bello! È possibile salvare 3 byte riducendo /\s*/al / */e rimuovendo le parentesi intornoj=0
nderscore

1
non potresti usare al ...posto di apply?
Ven

Grazie a entrambi - che salva 9 caratteri - L' operatore spread ( ...) è uno che non ho mai incontrato prima.
MT0,

[].concat(...s.split`N`.map(x=>x.split(/ */).map((x,i,a)=>x+(a[x]=a[x]?++j:j=1)))).sort().map((x,i,a)=>a[i-1]<x?x[0]:'').join``;
l4m2

11

Perl - 46 byte

#!perl -p
$s=~s/$_//ifor/./g;$s.=uc}for(sort$s=~/\w/g){

Contando lo shebang come 1. Questa è una traduzione libera della soluzione Ruby di seguito.


Rubino 1,8 - 72 byte

s='';s+=$_.upcase.scan(/./){s.sub!$&,''}while gets;$><<s.scan(/\w/).sort

L'input è preso da stdin.

Esempio di utilizzo:

$ more in.dat
Hello
I love cat
I love dog
I love mommy
Mommy loves daddy

$ ruby fridge-letters.rb < in.dat
ACDDDEGHILLMMMOOSTVYY

L'output deve essere ordinato.
Matt,

@Matt ora risolto.
primo

Bello. Se il tuo Perl è vagamente recente, vorrai uno spazio tra /ie for.
tobyink

8

Python - 206 204 199 177 145 129 117 94 88 caratteri

print(''.join(c*max(l.lower().count(c)for l in open(f))for c in map(chr,range(97,123))))

Non ero sicuro di come avrei dovuto ottenere il nome del file, quindi al momento il codice presume che sia contenuto in una variabile denominata f. Per favore fatemi sapere se devo cambiarlo.


8
nello spirito di unix - potresti leggere dallo stdin.
romaninsh

5

3
Anche io sono nuovo, ma se salva i personaggi, perché no?

1
Assumendo fil nome del file di input e utilizzando lettere maiuscole (tutte le lettere del magnete sono comunque maiuscole), è possibile arrivare a 91:print(''.join([chr(i)*max(l.upper().count(chr(i))for l in open(f))for i in range(65,91)]))
Gabe

1
@ njzk2 bene, se lo eseguiamo nella console, in teoria stamperebbe il risultato da solo ...
Tal

6

Ruby 1.9+, 51 (o 58 o 60)

a=*$<
?a.upto(?z){|c|$><<c*a.map{|l|l.count c}.max}

Presuppone che tutto sia in minuscolo. L'insensibilità alle maiuscole costa 7 caratteri via .upcase, mentre l'insensibilità alle maiuscole e minuscole costa 9 caratteri via .downcase.


4

R (156, incl. File letto)

Con la tabella costruisco la tabella delle frequenze delle lettere per ogni frase. Quindi finisco col prendere per ogni lettera il valore massimo.

a=c();for(w in tolower(read.csv(fn,h=F)$V1))a=c(a,table(strsplit(w,"")[[1]]));a=tapply(seq(a),names(a),function(i)max(a[i]))[-1];cat(rep(names(a),a),sep="")

Ungolfed:

a=c()
words = read.csv(fn,h=F)$V1
for(w in tolower(words))
  a=c(a, table(strsplit(w, "")[[1]]))
a = tapply(seq(a), names(a), function(i) max(a[i]))[-1] ## The -1 excludes the space count.
cat(rep(names(a), a), sep="")

Soluzione:

acdddeghillmmmoooooostuvyy

@lambruscoAcido potresti vettorializzare le tre prime righe (del codice ungolfed) che ti darebbero a=unlist(lapply(readLines(fn),function(x)table(strsplit(tolower(x),""))));a=tapply(seq(a),names(a),function(i)max(a[i]))[-1];cat(rep(names(a),a),sep=""), ma sono solo 3 caratteri più corti
jkd

Un altro approccio con solo 112 caratteri sarebbe cat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")assumere fil nome del file
jkd

4

Haskell, 109 108

import Data.List
import Data.Char
main=interact$sort.filter(/=' ').foldl1(\x y->x++(y\\x)).lines.map toLower

Il programma legge da stdin e scrive su sdtout.

È abbastanza semplice: suddivide la stringa in un elenco di righe e la ricostruisce ripetendo l'elenco e aggiungendo le nuove lettere contenute in ciascuna riga.


Oh wow, perché non ho mai sentito parlare di (\\) prima?
Flonk,


4

Perl 6: 56 53 caratteri; 58 55 byte

say |sort
([∪] lines.map:{bag comb /\S/,.lc}).pick(*)

Per ogni riga, questo passa attraverso di essa per i caratteri non spaziali della stringa in maiuscolo ( comb /\S/,.lc) e crea un Bag, o una raccolta di ogni carattere e quante volte si verifica. [∪]prende l'unione delle Bags su tutte le linee, ottenendo il numero massimo di volte in cui si è verificato il personaggio. .pick(*)è hack-y qui, ma è il modo più breve per ottenere tutti i personaggi Bagreplicati dal numero di volte che si è verificato.

EDIT: Per vedere se sarebbe più breve, ho provato a tradurre la risposta di Ruby dell'istocrate . Ha 63 caratteri, ma mi piace ancora molto l'approccio:

$!=lines».lc;->$c{print $c x max $!.map:{+m:g/$c/}} for"a".."z"

3

Haskell, 183 162 159

Supponendo che il file sia dentro file.txt!

import Data.Char
import Data.List
main=readFile"file.txt">>=putStr.concat.tail.map(tail.maximum).transpose.map(group.sort.(++' ':['a'..'z'])).lines.map toLower

Se file.txt contiene, ad esempio

abcde
abcdef
aaf

Lo script verrà emesso

aabcdef

Fondamentalmente sto aggiungendo l'intero alfabeto a ciascuna riga, in modo che quando si raggruppano e si ordinano, sono sicuro che finirò con un elenco che contiene 27 elementi. Successivamente, traspongo la "tabella delle frequenze", in modo tale che ciascuna riga di questo array sia costituita dalle frequenze di una singola lettera in ciascuna riga, ad es ["a","","aaa","aa","aaaa"]. Scelgo quindi il massimo di ciascun array (che funziona esattamente come voglio a causa del funzionamento Orddell'istanza di stringhe), quindi rilascia la lettera che ho aggiunto all'inizio, elimina gli spazi e genera il risultato.


1
Invece di drop 1, basta usaretail
Bergi

@Bergi Haha derp, grazie! L'ho cambiato nel post.
Flonk,

3

C, 99 caratteri

t[256];main(c){for(--*t;++t[1+tolower(getchar())];);for(c=97;c<123;c++)while(t[c]--)putchar(c-1);}

Si arresta in modo anomalo se viene fornita meno di una nuova riga. Penso che potrebbe essere risolto abbastanza facilmente.


Ho provato, ma non ha prodotto risultati corretti. gist.github.com/romaninsh/11159751
romaninsh

3

kdb (q / k): 59 caratteri:

d:.Q.a! 26#0
.z.pi:{d|:.Q.a##:'=_y}.z.exit:{-1@,/.:[d]#'!:d}
  • genera un dizionario seme preordinato dall'alfabeto .Qa
  • elabora ogni riga di input, converti in minuscolo, raggruppa in dizionario, conta ogni elemento, prende i caratteri alfabetici dal risultato (ad esempio potenzia spazi, newline, ecc.) e usa max-assegnato a globale d per mantenere un totale parziale.
  • definire il gestore di uscita, che viene passato a .z.pi per salvare un delimitatore ma altrimenti non utilizzato lì. Prendi da ogni valore-chiave per generare un elenco di caratteri, appiattire e infine stampare su stdout.

-1 aggiunge una nuova riga, l'utilizzo di 1 salverebbe un carattere ma non genererà l'output specificato. Vorrei poter sbarazzarmi del .z.pi / .z.exit boilerplate, che rimuoverebbe 14 caratteri.

Modifica: evita l'uso di inter / asc usando il dizionario dei semi.


3

Perl, 46

for$:(a..z){$a[ord$:]|=$:x s/$://gi}}{print@a

Ecco un'altra soluzione Perl, legge da STDIN, richiede -nswitch (+1 per contare), si lega al punteggio di Primo ma corre senza lamentele :-). Sfrutta il fatto che oril risultato bit per bit ha una lunghezza dell'argomento stringa più lunga.


1
provato con il mio test e ha funzionato benissimo.
romaninsh,

3

Sto aggiungendo la mia soluzione:

Bash - 72

Suppone che l'input sia nel file "i"

for x in {A..Z};do echo -n `cat i|sed "s/[^$x]//g"|sort -r|head -1`;done

Spiegazione

Per ogni possibile lettera, la filtra solo dal file di input risultando in qualcosa del genere:

AAA
A
A

AAAA

A
AAAAAAAAAAAAAAAA

Quindi il risultato viene ordinato e viene selezionata la linea più lunga. echo -nè lì per rimuovere le nuove righe.


3

Bash, 171 159 158, 138 con uscita spazzatura

Richiede input solo in minuscolo. Presuppone che il file sia chiamato _(trattino basso). Massimo di 26 righe nel file di input a causa dei fastidiosi nomi di file che splitcrea (xaa, xab ... xaz, ???).

In bash, {a..z}uscite a b c d e f ....

touch {a..z}
split _ -1
for l in {a..z}
do for s in {a..z}
do grep -so $l xa$s>b$l
if [ `wc -l<b$l` -ge `wc -l<$l` ]
then mv b$l $l
fi
done
tr -d '\n'<$l
done

Uscita campione

acdddeghillmmmoostvyy

Spiegazione

touch {a..z}

Crea file che leggeremo più avanti in modo che Bash non si lamenti del fatto che non esistano. Se rimuovi questa riga risparmierai 13 caratteri ma otterrai un sacco di output spazzatura.

split _ -1

Dividi il file di input in sezioni, ciascuna contenente 1 riga. I file creati da questo comando sono denominati xaa, xab, xac e così via, non ho idea del perché.

for l in {a..z}
do for s in {a..z}

Per ogni lettera $lleggere tutte le righe memorizzate nei file xa$s.

do grep -so $l xa$s>b$l

Rimuovere l' -sinterruttore per salvare 1 carattere e ottenere un sacco di output spazzatura. Impedisce grepdi lamentarsi di file inesistenti (si verificherà a meno che non si disponga di 26 righe di input). Questo elabora il file xa$s, rimuovendo qualsiasi cosa tranne le occorrenze $le inviando l'output al file b$l. Quindi "I love mommy" diventa "mmm" con nuove righe dopo ogni lettera quando $lè m.

if [ `wc -l<b$l` -ge `wc -l<$l` ]

Se il numero di righe nel file che abbiamo appena creato è maggiore o uguale a (ovvero più lettere poiché esiste una lettera per riga) il numero di righe nel nostro risultato più alto finora (memorizzato in $l...

then mv b$l $l

... memorizza il nostro nuovo record nel file $l. Alla fine di questo ciclo, quando abbiamo esaminato tutte le righe, il file $lmemorizzerà x righe ognuna contenente la lettera $l, dove x è il numero più alto di occorrenze di quella lettera in una singola riga.

fi
done
tr -d '\n'<$l

Stampa il contenuto del nostro file per quella particolare lettera, rimuovendo nuove righe. Se non desideri rimuovere le nuove righe, modifica la riga con trin echo $l, salvando 6 caratteri.

done

Provato con GNU bash, versione 3.2.51 (apple), ma il file '-l1aa' in una cartella corrente contenente dati di input ..
romaninsh

@romaninsh Potrebbe essere che tu abbia una versione diversa di split(da coreutils). Attualmente sto eseguendo GNU bash 4.3.8 e GNU coreutils 8.21 su Ubuntu 14.04 e funziona benissimo (ha funzionato anche su Ubuntu 13.10 prima dell'aggiornamento). Tuttavia, ho dovuto posizionare il programma e il file di input in una directory separata affinché funzionasse correttamente - sospetto che ciò fosse dovuto solo ai milioni di file spazzatura nella mia cartella home .

@romaninsh in effetti, se guardi il comando esatto nello script: split _ -l1e noti che il tuo input è stato salvato -l1aa, penso che la tua versione di split non sia riconosciuta -l1come un'opzione e invece prenderla come prefisso per l'output . Prova a mettere uno spazio tra -le 1, o mettere --lines=1, o solo -1(questa sembra essere una sintassi obsoleta e più golfosa con la quale ora aggiornerò il post).

3

C #, 172 byte

var x="";foreach(var i in File.ReadAllText(t).ToLower().Split('\r','\n'))foreach(var j in i)if(x.Count(c=>c==j)<i.Count(c=>c==j))x+=j;string.Concat(x.OrderBy(o=>o)).Trim();

Intelligente ... intelligente ... Ho pensato di giocare con Linq, ma dubito che sarà breve come queste forcate contorte :)
Noctis

2

Python 2 - 129

Idea di @Tal

a,r=[0]*26,range(26)
for l in open('f'):a=[max(a[i],l.lower().count(chr(i+97)))for i in r]
print''.join(chr(i+97)*a[i]for i in r)

Un altro paio di modi per fare la stessa cosa nello stesso numero di personaggi:

a=[0]*26
b='(chr(i+97)))for i in range(26)'
exec'for l in open("f"):a=[max(a[i],l.lower().count'+b+']\nprint"".join(a[i]*('+b+')'

a=[0]*26
b='(chr(i+97)))for i in range(26))'
exec'for l in open("f"):a=list(max(a[i],l.lower().count'+b+'\nprint"".join(a[i]*('+b

Ciò presuppone che il file sia salvato come f in una directory accessibile. Questo programma è direttamente eseguibile, senza input aggiuntivo necessario.


Perché il voto negativo? Scusa se ho fatto qualcosa di sbagliato.
isaacg,

2

Mathematica v10 - 110

Non è ancora uscito, ma leggendo la nuova documentazione con molta attenzione, penso che dovrebbe funzionare:

StringJoin@MapIndexed[#2~Table~{#1}&,Rest@Merge[Counts/@Characters@StringSplit[ToLowerCase@Input[],"\n"],Max]]

2

Scala, 125 caratteri

val i=""::io.Source.stdin.getLines.toList.map(_.toLowerCase);println('a'to'z'map(c=>(""+c)*i.map(_.count(_==c)).max)mkString)

Per prima cosa ho letto l'input, convertendolo in minuscolo e aggiungendo una riga vuota.

Quindi per ogni lettera da aaz ripeto il numero massimo di volte che appare in una delle righe (ecco perché ho bisogno della riga vuota: maxnon può essere chiamata su un input enpty). Quindi unisco i risultati e stampo sull'output.

Per leggere da un file, sostituirlo stdincon fromFile("FILENAME"), aumentando la dimensione del codice a 132 caratteri + lunghezza del nome file.


2

Javascript, 261 caratteri

eval('s=prompt().toUpperCase().split("\\n");Z=[########0,0];H=Z.slice();s@r){h=Z.slice();r.split("")@c){if(c.match(/\\w/))h[c.charCodeAt(0)-65]++});H=H@V,i){return V>h[i]?V:h[i]})});s="";H@n,i){s+=Array(n+1).join(String.fromCharCode(i+97))});s'.replace(/@/g,".map(function(").replace(/#/g,"0,0,0,"))

Rimuovere eval(...)ed eseguire per ottenere il codice reale; questo è ( un po ' ) compresso.

smulti-funzioni come array di linee e come stringa emessa, hcontiene l'istogramma delle lettere per riga e Hcontiene l'istogramma con i valori massimi fino ad ora. Non distingue tra maiuscole e minuscole e ignora qualsiasi cosa tranne az e AZ (penso ... le matrici JS a volte sono strane).

Ora corretto :)


Questo è solo un totale dei personaggi, non proprio quello che la domanda ha posto. Le lettere dovrebbero essere sommate per essere il minimo indispensabile per formare una singola frase nell'input, non tutte. Mi piace piuttosto il tuo approccio per evitare la necessità di ordinare l'output.
Matt,

@ Matt oh esatto ... Lo riparerò più tardi. Non ho davvero tempo in questo momento.
tomsmeding,

1
@Mi chiedevo cosa stesse succedendo fino a quando non sono arrivato alla fine. Mi piace :)
Matt

2

JavaScript ( ES5 ) 141 byte

Supponendo che la variabile ssia la stringa di input senza requisiti di verifica del caso e output dell'array:

for(a in s=s[o=_='',y='split']('\n'))for(i=0;x=s[a][i++];)o+=x!=0&&(l=s[a][y](x).length-~-o[y](x).length)>0?Array(l).join(x):_;o[y](_).sort()

Ho testato la tua soluzione e cercavo un output all'interno di "o", ma non sembra essere stato ordinato correttamente. (vedi gist.github.com/romaninsh/11159751 )
romaninsh

@romaninsh l'output che vedo nel tuo gist sembra ordinato correttamente
nderscore

Sì, questo è un output di riferimento / corretto. Quando ho provato il tuo codice, ho ricevuto questo: gist.github.com/romaninsh/11161018
romaninsh

Mi scuso se ho eseguito il tuo esempio in modo errato.
romaninsh,

@romaninsh ah, avevo previsto che fosse eseguito nella console del browser. Ecco una versione riformattata che funziona sul nodo: gist.github.com/nderscore/96aa888c77d275c26c15
nderscore

2

PowerShell - 141

Legge il testo da un file denominato "a".

$x=@{}
gc a|%{[char[]]$_|group|%{$c=$_.name.tolower().trim()
$n=$_.count;$x[$c]=($n,$x[$c])[$n-lt$x[$c]]}}
($x.Keys|sort|%{$_*$x[$_]})-join""

2

Groovy, 113/127 102/116 caratteri

Supponendo che il file sia tutto in un caso (102 caratteri):

t=new File('f').text;t.findAll('[A-Z]').unique().sort().each{c->print c*t.readLines()*.count(c).max()}

Supponendo che il file sia in maiuscolo (116 caratteri):

t=new File('f').text.toUpperCase();t.findAll('[A-Z]').unique().sort().each{c->print c*t.readLines()*.count(c).max()}

Fondamentalmente:

  • t=new File('f').text Per ottenere il testo del file.
  • t.findAll('[A-Z]').unique().sort().each{c-> Per ottenere i personaggi unici, ordinali e itera.
  • print c*t.readLines()*.count(c).max() Ottieni le ricorrenze massime in una sola riga e stampa il personaggio più volte.

2

Bash (principalmente awk) - 172 163 157

awk -v FS="" '{delete l;for(i=1;i<=NF;i++)l[toupper($i)]++;for(i in l)o[i]=(o[i]>l[i]?o[i]:l[i])}END{for(i in o)for(j=0;j<o[i];j++)print i}'|sort|tr -d ' \n'

Il testo deve essere reindirizzato a awk (o specificato come file).

Esempio di input

Hello
I love cat
I love dog
I love mommy
Mommy loves daddy

Esempio di output

ACDDDEGHILLMMMOOSTVYY

PHP (probabilmente potrebbe essere migliore) - 174 210

$o=array();foreach(explode("\n",$s) as $a){$l=array();$i=0;while($i<strlen($a)){$k=ucfirst($a[$i++]);if($k==' ')continue;$o[$k]=max($o[$k],++$l[$k]);}}ksort($o);foreach($o as $k=>$v)for($i=0;$i<$v;$i++)echo $k;

Presuppone che la stringa sia contenuta nella variabile $ s

Esempio di input

Hello
I love cat
I love dog
I love mommy
Mommy loves daddy

Esempio di output

ACDDDEGHILLMMMOOSTVYY

2

Mi rendo conto che probabilmente questa non è la risposta più efficiente, ma volevo comunque provare a risolvere il problema. Ecco la mia variante di ObjC:

- (NSArray *) lettersNeededForString:(NSString *)sourceString {
    sourceString = [sourceString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    sourceString = [sourceString stringByReplacingOccurrencesOfString:@" " withString:@""];
    const char * sourceChars = sourceString.UTF8String;
    NSMutableArray * arr = [NSMutableArray new];
    for (int i = 0; i < sourceString.length; i++) {
        [arr addObject:[NSString stringWithFormat:@"%c", sourceChars[i]]];
    }
    return [arr sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}    

Quindi puoi chiamarlo per qualsiasi stringa:

NSArray * letters = [self lettersNeededForString:@"Hello\nI love cat\nI love dog\nI love mommy\nMommy loves daddy"];
NSLog(@"%@",letters);

Stavo pensando ad applicazioni con grandi quantità di testo e preferirei non dover contare il mio array. Per questo, ho aggiunto al metodo per ottenere questo:

- (NSDictionary *) numberOfLettersNeededFromString:(NSString *)sourceString {

    sourceString = [sourceString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    sourceString = [sourceString stringByReplacingOccurrencesOfString:@" " withString:@""];
    const char * sourceChars = sourceString.UTF8String;
    NSMutableArray * arr = [NSMutableArray new];
    for (int i = 0; i < sourceString.length; i++) {
        [arr addObject:[NSString stringWithFormat:@"%c", sourceChars[i]]];
    }

    static NSString * alphabet = @"abcdefghijklmnopqrstuvwxyz";
    NSMutableDictionary * masterDictionary = [NSMutableDictionary new];
    for (int i = 0; i < alphabet.length; i++) {
        NSString * alphabetLetter = [alphabet substringWithRange:NSMakeRange(i, 1)];
        NSIndexSet * indexes = [arr indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
            if ([[(NSString *)obj lowercaseString] isEqualToString:alphabetLetter]) {
                return YES;
            }
            else {
                return NO;
            }
        }];

        masterDictionary[alphabetLetter] = @(indexes.count);
    }

    return masterDictionary;
}

Esegui come:

NSDictionary * lettersNeeded = [self numberOfLettersNeededFromString:@"Hello\nI love cat\nI love dog\nI love mommy\nMommy loves daddy"];
NSLog(@"%@", lettersNeeded);

Ti darà:

{a = 2; b = 0; c = 1; d = 4; e = 5; f = 0; g = 1; h = 1; i = 3; j = 0; k = 0; l = 6; m = 6; n = 0; o = 8; p = 0; q = 0; r = 0; s = 1; t = 1; u = 0; v = 4; w = 0; x = 0; y = 3; z = 0; }

Il che penso sia meglio se avessi una grande quantità di testo e avessi solo bisogno di sapere quante di ogni lettera avrei bisogno.



2

Python 2, 154 byte

import collections
c = collections.Counter()
for line in open("input.txt"):
    c |= collections.Counter(line.upper())
print "".join(sorted(c.elements()))

Benvenuti in PCG! Questo sito supporta la sintassi Markdown, che puoi usare per formattare il tuo codice, in modo che appaia bello: basta rientrare ogni riga di spazi di codice 4.
algoritmo

Dovrai aggiungere i caratteri necessari per importare le raccolte.
isaacg,

1
non risponde alla domanda, poiché è necessaria la quantità minima di lettere per scrivere ogni frase singolarmente. Nel tuo codice, hai prodotto il numero di lettere necessarie per scrivere tutte le frasi contemporaneamente.
njzk2,

Ti manca un salla fine importdell'istruzione e il withblocco manca di rientro. E poiché questo è il golf del codice, ti sarebbe di grande beneficio rimuovere gli spazi bianchi non necessari dove possibile.
Fraxtil,

dato che si tratta di code golf, rimuovi l'istruzione with (basta passare sopra una chiamata per aprire) e non credo che gli elementi debbano essere ordinati.
RemcoGerlich,

2

C, 298 byte

char c;
int j,n;
char C[26];
char D[26];
int main()
{
char a='a';
while((c=getchar())>=0)
{
c=tolower(c);
if(c>=a&&c<='z'){j=c-a;D[j]++;}
if(c=='\n'){
for(j=0;j<26;j++){
if(D[j]>C[j])
{C[j]=D[j];}
D[j]=0;
}
}
}
for(j=0;j<26;j++)
{
n=C[j];
while(n--)
{
putchar(a+j);
}
}
}

L'array D contiene il conteggio delle lettere per ogni riga, quindi il conteggio massimo viene copiato in C.

Nota: ho inserito la mia risposta ieri ma ora non è elencato, forse ho premuto Elimina invece di Modifica per errore?


Sono solo 271 byte. Hai anche molte nuove linee estranee. Inoltre, puoi omettere il intda int main()e int j,n;.
nyuszika7h

Inoltre, la tua risposta precedente è ancora lì.
nyuszika7h

2

PHP, 143 byte

Supponendo che l'input sia passato in variabile $s:

$i=explode("\n",$s);foreach(range('a','z')as$c){$x=array_map(function($l)use($c){return substr_count($l,$c);},$i);echo str_repeat($c,max($x));}

Spiegazione

Per ogni possibile lettera sto mappando un array contenente un elenco di stringhe tramite una funzione definita dall'utente che sostituisce ogni riga con il numero di caratteri utilizzati. Per la lettera 'd' la linea "Mamma ama papà" sarà mappata in 3.

Successivamente trovo il massimo valore all'interno dell'array e della lettera di output proprio così tante volte. Ecco la versione multilinea:

$i=explode("\n",$s);
foreach(range('A','Z')as $c){
    $x=array_map(function($l)use($c){
        return substr_count($l,$c);
    },$i);
    echo str_repeat($c,max($x));
}

1

Python (209, con il campione incluso, 136 senza.):

from collections import*;c=Counter()
for i in ["Hello","I love cat", "I love Dog", "I love mommy", "Mommy loves daddy"]:
 for j in i.lower(): c[j]=max(c[j],list(i).count(j))
print "".join(sorted(c.elements()))

Pubblicherò un campione di PYG questo pomeriggio.


Non avevo idea che le stringhe di Python avessero un metodo di conteggio ... Non credo che sia considerato legittimo cambiare la mia risposta alla domanda per usare questa nuova conoscenza trovata? : p
Tal

@tal Non lo fanno. È un metodo di un elenco, se guardi più da vicino
Aprıʇǝɥʇuʎs

1
Oh, capisco ... ma in una svolta inaspettata risulta che anche le stringhe hanno questo metodo (comunque in 3.x)
Tal
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.