Alfabeto da minha filha


65

No outro dia, estávamos escrevendo frases com minha filha com uma carta de imã de geladeira. Embora pudéssemos fazer algumas ( I love cat), não tínhamos letras suficientes para as outras ( I love you too) devido a uma quantidade insuficiente de letras o(4)

Descobri então que, enquanto um conjunto incluía 3 eletras, tinha apenas 2 o. Provavelmente inspirado em http://en.wikipedia.org/wiki/Letter_frequency, isso ainda não reflete a situação real "na geladeira".

Problema

Dado o arquivo de texto em que cada linha contém uma "sentença de amostra" que alguém gostaria de escrever na geladeira, proponha um conjunto de alfabeto com quantidade mínima de letras, mas ainda o suficiente para escrever cada sentença individualmente.

Nota: ignore os casos, todas as letras do ímã são maiúsculas de qualquer maneira.

Entrada

O arquivo contém frases separadas por nova linha:

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

Resultado

Forneça uma lista ordenada de letras, onde cada letra aparece apenas quantas vezes é suficiente para escrever qualquer frase:

acdddeghillmmmoostvyy

(obrigado, isaacg!)

Vencedora

Implementação mais curta (código)

ATUALIZADO: Teste

Eu criei um teste extra e tentei com várias respostas aqui:

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


2
Deve haver uma carta vna saída;)
Antonio Ragagnin

40
É permitido / requerido substituir um de cabeça para baixo Mpor um Wou um de lado Npara um Z? ;-)
Ilmari Karonen

4
Basicamente, você pode construir qualquer letra usando Is.
swish

7
Mais seriamente, quando você diz "ignorar casos", você quer dizer que podemos assumir que a entrada já está no mesmo caso ou que devemos convertê-la no mesmo caso? Além disso, é aceitável que a saída inclua alguns espaços à esquerda?
Ilmari Karonen

3
@Doorknob:_\¯
Ilmari Karonen

Respostas:


18

GolfScript, 28/34 caracteres

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

O programa de 28 caracteres acima assume que todas as letras de entrada estão no mesmo caso. Se isso não for necessariamente assim, podemos forçá-los para maiúsculas, acrescentando {95&}%um código ao total de 34 caracteres:

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

Notas:

  • Para uma operação correta, a entrada deve incluir pelo menos uma nova linha. Isso será verdadeiro para arquivos de texto normais com novas linhas no final de cada linha, mas poderá não ser verdadeiro se a entrada consistir em apenas uma linha sem nenhuma nova linha à direita. Isso pode ser corrigido ao custo de dois caracteres extras, acrescentando n+o código.

  • A maiúscula usada na versão de 34 caracteres é realmente grosseira - mapeia letras ASCII em minúsculas para seus equivalentes em maiúsculas (e espaços para NULs), mas produz uma bagunça completa de números e maior pontuação. Estou assumindo que a entrada não incluirá nenhum desses caracteres.

  • A versão de 28 caracteres trata todos os caracteres de entrada (exceto novas linhas NULes). Em particular, se a entrada contiver espaços, alguns também aparecerão na saída; convenientemente, eles serão classificados antes de qualquer outro caractere ASCII imprimível. A versão de 34 caracteres, no entanto, ignora os espaços (porque acontece que eu posso fazer isso sem me custar caracteres extras).

Explicação:

  • O {95&}%prefixo opcional maiúscula a entrada zerando o sexto bit do código ASCII de cada byte de entrada ( ). Isso mapeia letras ASCII minúsculas para maiúsculas, espaços para bytes nulos e deixa as novas linhas inalteradas.95 = 64 + 31 = 10111112

  • n/divide a entrada na nova linha, e :aatribui a matriz resultante na variável a. Em seguida, {|}*calcula a união do conjunto das seqüências de caracteres na matriz, que (assumindo que a matriz tenha pelo menos dois elementos) gera uma sequência contendo todos os caracteres exclusivos (sem nova linha) na entrada.

  • O { }%loop a seguir itera sobre cada um desses caracteres exclusivos. Dentro do corpo do loop, o loop interno a{.[2$]--}%itera sobre as strings da matriz a, removendo de cada string todos os caracteres diferentes do que o loop externo está repetindo.

    O loop interno deixa o código ASCII do caractere atual na pilha, abaixo da matriz filtrada. Utilizamos isso repetindo a matriz filtrada tantas vezes quanto indicado pelo código ASCII ( *) antes de classificá-la ( $) e pegar o último elemento ( -1=). De fato, isso gera a cadeia mais longa da matriz filtrada (como todas consistem em repetições do mesmo caractere, a classificação lexicográfica apenas as classifica por comprimento), exceto se o caractere tiver o código ASCII zero e, nesse caso, não produzirá nada.

  • Finalmente, $no final apenas classifica a saída em ordem alfabética.


3
Surpreendente. TODO: Aprenda GolfScript!
DLosc

11
Você pode até mesmo reduzi-la a 26: n/:a{|}*{{{=}+,}+a%$-1=}%$.
Howard

13

J - 37 char

Lê de stdin, produz para o console.

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

1!:1]3é a chamada para stdin. tolower;._2executa dupla tarefa dividindo as linhas e tornando-as em minúsculas simultaneamente. Depois, contamos quantas vezes um caractere ocorre em cada linha com +/"2=/&a.e levamos o máximo em pontos sobre todas as linhas com >./.

Por fim, extraímos muitos caracteres de cada caractere do alfabeto #&a.. Isso inclui espaços - todos encontrados na frente devido ao seu baixo valor ASCII -, portanto, apenas excluímos espaços em branco iniciais dlb.


12

JavaScript (ECMAScript 6) - 148 139 135 caracteres

Versão 2:

Atualizado para usar a compreensão da matriz:

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

Versão 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])

Assume que:

  • A sequência de entrada está na variável s;
  • Podemos ignorar o caso da entrada (conforme especificado pela pergunta - isto é, tudo em maiúsculas ou minúsculas);
  • A saída é uma matriz de caracteres (que é o mais próximo que o JavaScript pode chegar ao requisito de lista de caracteres do OP); e
  • A saída deve ser exibida no console.

Com comentários:

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 você quiser:

  • Retorne-o como uma string e adicione .join('')-o no final;
  • Pegue a entrada de um usuário e substitua a svariável por prompt(); ou
  • Escreva como uma função fe adicione f=s=>ao início.

Corrida:

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

Dá a saída:

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

11
Agradável! Você pode salvar 3 bytes, reduzindo /\s*/a / */e removendo os parênteses em tornoj=0
nderscore

11
você não poderia usar em ...vez de apply?
Ven

Graças a vocês - que salvam 9 caracteres - o operador spread ( ...) é um que eu nunca encontrei antes.
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 bytes

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

Contando o shebang como 1. Esta é uma tradução simplificada da solução Ruby abaixo.


Ruby 1.8 - 72 bytes

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

A entrada é retirada de stdin.

Uso da amostra:

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

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

A saída precisa ser classificada.
Matt

@Matt agora corrigido.
Primo

Agradável. Se o seu Perl for vagamente recente, você precisará de um espaço entre /ie for.
tobyink

8

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

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

Eu não tinha certeza de como deveria obter o nome do arquivo, portanto, no momento, o código pressupõe que ele esteja contido em uma variável chamada f. Por favor, deixe-me saber se eu preciso mudar isso.


8
no espírito do unix - você pode ler de stdin.
romaninsh

5
sempre torne o nome do arquivo com um caractere ...

3
@ Tal Também sou novo, mas se ele salva personagens, por que não?

11
Ao assumir fo nome do arquivo de entrada e usar letras maiúsculas (todas as letras do ímã são maiúsculas de qualquer maneira), você pode reduzi-lo a 91:print(''.join([chr(i)*max(l.upper().count(chr(i))for l in open(f))for i in range(65,91)]))
Gabe

11
@ njzk2 bem, se corremos isto no console, em teoria, seria apenas imprimir o resultado por si só ...
Tal

6

Ruby 1.9+, 51 (ou 58 ou 60)

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

Assume que tudo está em minúsculas. A diferenciação entre .upcasemaiúsculas e minúsculas custa 7 caracteres via , enquanto a diferenciação entre maiúsculas e minúsculas custa 9 caracteres via .downcase.


4

R (156, incl. Arquivo lido)

Com a tabela , construo a tabela de frequência de letras para cada sentença. Então, acabei tomando para cada letra o valor máximo.

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

Solução:

acdddeghillmmmoooooostuvyy

@lambruscoAcido você poderia vetorizar as três primeiras linhas (do código ungolfed) que lhe daria 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=""), mas é apenas 3 personagens mais curto
JKD

Outra abordagem com apenas 112 caracteres seria cat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")assumir fo nome do arquivo
jkd 28/02

4

Haskell, 109 108

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

O programa lê de stdin e grava em sdtout.

É bem direto: quebra a string em uma lista de linhas e a reconstrói iterando na lista e adicionando as novas letras contidas em cada linha.


Oh uau, por que nunca ouvi falar de (\\) antes?
Flonk


4

Perl 6: 56 53 caracteres; 58 55 bytes

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

Para cada linha, ela procura por caracteres não espaciais da string de caixa inferior ( comb /\S/,.lc) e cria uma Bagou uma coleção de cada caractere e quantas vezes ocorre. [∪]leva a união dos Bags sobre todas as linhas, que obtém o número máximo de vezes que o personagem ocorreu. .pick(*)é hack-y aqui, mas é a maneira mais curta de obter todos os caracteres Bagreplicados pelo número de vezes que ocorreu.

EDIT: Para ver se seria mais curto, tentei traduzir a resposta Ruby do histocrata . São 63 caracteres, mas ainda gosto muito da abordagem:

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

3

Haskell, 183 162 159

Supondo que o arquivo esteja 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 contiver, por exemplo

abcde
abcdef
aaf

O script exibirá

aabcdef

Basicamente, estou anexando o alfabeto inteiro a cada linha, para que, ao agrupar e classificar, tenha certeza de que terminarei com uma lista que contenha 27 elementos. Em seguida, transponho a "tabela de frequências", de modo que cada linha desse array consista nas frequências de uma única letra em cada linha, por exemplo ["a","","aaa","aa","aaaa"]. Depois, escolho o máximo de cada matriz (que funciona exatamente como eu quero por causa de como a Ordinstância de Strings funciona) e largo a letra que eu anexei no início, livre-me dos espaços e produzo o resultado.


11
Em vez de drop 1, basta usartail
Bergi

@ Bergi Haha derp, obrigado! Eu mudei no post.
Flonk

3

C, 99 caracteres

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

Falha se menos de uma nova linha for fornecida. Eu acho que poderia ser corrigido facilmente.


Eu tentei, mas não produziu resultados corretos. gist.github.com/romaninsh/11159751
romaninsh

3

kdb (q / k): 59 caracteres:

d:.Q.a! 26#0
.z.pi:{d|:.Q.a##:'=_y}.z.exit:{-1@,/.:[d]#'!:d}
  • gerar dicionário de sementes pré-classificado a partir do alfabeto .Qa
  • processe cada linha de entrada, converta para minúscula, agrupe em dicionário, conte cada elemento, obtenha caracteres alfabéticos do resultado (ou seja, espaços de remoção, novas linhas, etc, nesta fase) e use max-assign para global d para manter um total em execução.
  • defina o manipulador de saída, que é passado para .z.pi para salvar um delimitador, mas que não é usado lá. Pegue em cada valor-chave para gerar a lista de caracteres, achatar e finalmente imprimir em stdout.

-1 adiciona uma nova linha, usar 1 salvaria um caractere, mas não geraria a saída especificada. Gostaria de poder me livrar do clichê .z.pi / .z.exit, que removeria 14 caracteres.

Editar: evite o uso de inter / asc usando o dicionário de sementes.


3

Perl, 46

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

Aqui está outra solução Perl, lê STDIN, requer -ntroca (+1 para contar), vincula-se à pontuação do primo, mas roda sem queixas :-). Explora o fato de que oro resultado do bit a bit possui um comprimento maior do argumento da string.


11
tentei com o meu teste e funcionou muito bem.
romaninsh

3

Estou adicionando minha própria solução:

Bash - 72

Assume que a entrada está no arquivo "i"

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

Explicação

Para cada letra possível, filtra-a apenas do arquivo de entrada, resultando em algo como isto:

AAA
A
A

AAAA

A
AAAAAAAAAAAAAAAA

Em seguida, o resultado é classificado e a linha mais longa é selecionada. echo -nexiste para remover novas linhas.


3

Bash, 171 159 158, 138 com saída de lixo eletrônico

Requer entrada somente em minúsculas. Supõe que o arquivo seja chamado _(sublinhado). Máximo de 26 linhas no arquivo de entrada devido aos nomes de arquivos irritantes que splitcria (xaa, xab ... xaz, ???).

Em bash, {a..z}saídas 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

Saída de amostra

acdddeghillmmmoostvyy

Explicação

touch {a..z}

Crie arquivos dos quais leremos mais tarde, para que o bash não reclame que eles não existem. Se você remover esta linha, você salvará 13 caracteres, mas terá muita saída indesejada.

split _ -1

Divida o arquivo de entrada em seções, cada uma armazenando 1 linha. Os arquivos criados por este comando são nomeados xaa, xab, xac e assim por diante, não faço ideia do porquê.

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

Para cada letra, $lleia todas as linhas armazenadas nos arquivos xa$s.

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

Remova a -sopção para economizar 1 caractere e obter muita saída indesejada. Impede grepqueixas sobre arquivos inexistentes (ocorrerão a menos que você tenha 26 linhas de entrada). Isso processa o arquivo xa$s, removendo tudo menos ocorrências $le enviando saída para o arquivo b$l. Então "eu amo mamãe" se torna "mmm" com novas linhas após cada letra quando $lé m.

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

Se o número de linhas no arquivo que acabamos de criar for maior ou igual a (ou seja, mais letras, uma vez que existe uma letra por linha), o número de linhas em nosso resultado mais alto até agora (armazenado em $l) ...

then mv b$l $l

... armazenar nosso novo registro no arquivo $l. No final desse loop, quando passamos por todas as linhas, o arquivo $larmazenará x linhas cada uma contendo a letra $l, onde x é o maior número de ocorrências dessa letra em uma única linha.

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

Envie o conteúdo do nosso arquivo para essa letra específica, removendo novas linhas. Se você não deseja remover as novas linhas, altere a linha com trpara echo $l, salvando 6 caracteres.

done

Tentei com o GNU bash, versão 3.2.51 (apple), mas o arquivo '-l1aa' em uma pasta atual contendo dados de entrada ..
romaninsh

@romaninsh Pode ser que você tenha uma versão diferente split(do coreutils). Atualmente, estou executando o GNU bash 4.3.8 e o GNU coreutils 8.21 no Ubuntu 14.04 e funciona bem (também funcionou no Ubuntu 13.10 antes da atualização). No entanto, eu tive que colocar o programa e o arquivo de entrada em um diretório separado para que funcionasse corretamente - suspeito que isso ocorreu apenas por causa dos milhões de arquivos indesejados na minha pasta pessoal .

@romaninsh, de fato, se você olhar para o comando exato no script: split _ -l1e perceber que sua entrada está sendo salva -l1aa, acho que sua versão split não está sendo reconhecida -l1como uma opção e, em vez disso, a considera um prefixo de saída . Tente colocar um espaço entre -le 1, ou colocar --lines=1, ou apenas -1(isso parece ser uma sintaxe obsoleta e com mais golfe, com a qual agora atualizarei a postagem).

3

C #, 172 bytes

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

Inteligente ... inteligente ... Eu pensei sobre o jogo com o LINQ, mas duvido que vai ser tão curto quanto estes foreachs contorcidos :)
Noctis

2

Python 2-129

Ideia de @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)

Mais algumas maneiras de fazer a mesma coisa no mesmo número de caracteres:

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

Isso pressupõe que o arquivo seja salvo como f em um diretório acessível. Este programa é diretamente executável, sem necessidade de entrada extra.


Por que o voto negativo? Desculpe se fiz algo errado.
Isaacg

2

Mathematica v10-110

Ainda não saiu, mas lendo a nova documentação com muito cuidado, acho que isso deve funcionar:

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

2

Scala, 125 caracteres

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

Primeiro, li a entrada, convertendo-a em minúsculas e adicionando uma linha vazia.

Então, para cada letra de aaté zeu repito essa letra o número máximo de vezes que ela aparece em qualquer uma das linhas (é por isso que eu preciso da linha vazia: maxnão pode ser chamada em uma entrada vazia). Então eu apenas juntei os resultados e imprimi na saída.

Para ler de um arquivo, substitua stdinpor fromFile("FILENAME"), aumentando o tamanho do código para 132 caracteres + comprimento do nome do arquivo.


2

Javascript, 261 caracteres

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

Remova eval(...)oe execute para obter o código real; isto é ( um pouco ) comprimido.

smulti-funções como a matriz de linhas e como a sequência de saída, hcontém o histograma das letras por linha e Hcontém o histograma com os valores máximos até agora. Não faz distinção entre maiúsculas e minúsculas e ignora qualquer coisa, exceto az e AZ (acho ... matrizes JS às vezes são estranhas).

Agora corrija :)


Isso totaliza os personagens, não exatamente o que a pergunta fez. As letras devem ser totalizadas como o mínimo definido para formar qualquer sentença na entrada, nem todas. Eu gosto bastante da sua abordagem para evitar a necessidade de classificar a saída.
Matt

@ Matt oh está certo ... Eu vou consertar isso mais tarde. Realmente não tenho tempo agora.
tomsmeding

11
Gostaria de saber o que estava acontecendo com o @até que eu cheguei ao fim. I like it :)
Matt

2

JavaScript ( ES5 ) 141 bytes

Supondo que variável sé a sequência de entrada sem requisitos de verificação de caso e saída de matriz:

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

Testei sua solução e estava procurando dentro de "o" uma saída, mas ela não parece ser classificada corretamente. (consulte gist.github.com/romaninsh/11159751 )
romaninsh

@romaninsh a saída que eu vejo na sua essência parece ordenada corretamente
nderscore

Sim, isso é uma referência / saída correta. Quando tentei o seu código, obtive o seguinte: gist.github.com/romaninsh/11161018
romaninsh

Desculpas se eu executei o seu exemplo incorretamente.
romaninsh

@romaninsh ah, eu pretendia que ele fosse executado no console do navegador. Aqui está uma versão reformatada que funciona no nó: gist.github.com/nderscore/96aa888c77d275c26c15
nderscore

2

PowerShell - 141

Lê o texto de um arquivo chamado '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 caracteres

Supondo que o arquivo esteja em um único caso (102 caracteres):

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

Supondo que o arquivo esteja em maiúsculas e minúsculas (116 caracteres):

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

Basicamente:

  • t=new File('f').text Para obter o texto do arquivo.
  • t.findAll('[A-Z]').unique().sort().each{c-> Para obter os caracteres únicos, ordene-os e itere.
  • print c*t.readLines()*.count(c).max() Obtenha o máximo de ocorrências em uma única linha e imprima o caractere várias vezes.

2

Bash (principalmente inábil) - 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'

O texto precisa ser canalizado para o awk (ou especificado como um arquivo).

Exemplo de entrada

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

Saída de exemplo

ACDDDEGHILLMMMOOSTVYY

PHP (provavelmente poderia ser melhor) - 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;

Assume que a sequência está contida na variável $ s

Exemplo de entrada

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

Saída de exemplo

ACDDDEGHILLMMMOOSTVYY

2

Sei que essa provavelmente não é a resposta mais eficiente, mas queria tentar resolver o problema de qualquer maneira. Aqui está minha variação de 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:)];
}    

Então você pode chamá-lo para qualquer string:

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

Eu estava pensando em aplicativos com grandes quantidades de texto e preferia não ter que contar minha matriz. Para isso, eu adicionei ao método para obter isso:

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

Executar como:

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

Darei à você:

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

O que eu acho melhor se eu tivesse uma quantidade muito grande de texto e só precisasse saber quantas letras de cada letra eu precisaria.



2

Python 2, 154 bytes

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

Bem-vindo ao PCG! Este site suporta a sintaxe do Markdown, que você pode usar para formatar seu código, para que ele pareça agradável: apenas indente cada linha do código 4 espaços.
algorithmshark

Você precisará adicionar os caracteres necessários para importar coleções.
Isaacg

11
não responde à pergunta, pois você precisa da quantidade mínima de letras para escrever cada frase individualmente. No seu código, você gera o número de letras necessárias para escrever todas as frases ao mesmo tempo.
Njzk2

Você está faltando um sno final da importinstrução e o withbloco não possui recuo. E, como se trata de código de golfe, seria muito útil remover espaços em branco desnecessários sempre que possível.
Fraxtil

como esse é o código golf, remova a instrução with (basta fazer um loop em uma chamada para abrir) e não acho que os elementos precisem ser classificados.
RemcoGerlich 13/04

2

C, 298 bytes

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

A matriz D contém uma contagem de letras para cada linha e a contagem máxima é copiada para C.

Nota: coloquei minha resposta ontem, mas agora não está listado, talvez eu tenha pressionado excluir em vez de editar por engano?


São apenas 271 bytes. Você também tem muitas novas linhas estranhas. Além disso, você pode omitir o intde int main()e int j,n;.
usar o seguinte código

Além disso, sua resposta anterior ainda está lá.
precisa saber é o seguinte

2

PHP, 143 bytes

Supondo que a entrada seja passada na variável $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));}

Explicação

Para cada letra possível, estou mapeando um array contendo uma lista de strings por meio de uma função definida pelo usuário que substitui cada linha pelo número de caracteres usados. Para a letra 'd', a linha "Mamãe ama papai" será mapeada em 3.

Posteriormente, encontro o valor máximo dentro da matriz e na letra de saída tantas vezes. Aqui está a versão em várias linhas:

$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, com a amostra incluída, 136 sem.):

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

Vou postar uma amostra de PYG esta tarde.


Eu não tinha ideia de que as seqüências de caracteres Python tinham um método de contagem ... Não acho que seja legítimo alterar minha resposta à pergunta para usar esse novo conhecimento encontrado? : p
Tal

@tal Eles não. É um método de uma lista, se você olhar mais de perto
ɐɔıʇǝɥʇuʎs

11
Oh, eu vejo ... mas em uma reviravolta inesperada despeja cordas aparentemente têm este método também (em 3.x de qualquer maneira)
Tal
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.