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 e
letras, 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:
v
na saída;)M
por umW
ou um de ladoN
para umZ
? ;-)I
s._\¯
Respostas:
GolfScript, 28/34 caracteres
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: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
NUL
s), 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
NUL
es). 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:a
atribui a matriz resultante na variávela
. 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 internoa{.[2$]--}%
itera sobre as strings da matriza
, 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.fonte
n/:a{|}*{{{=}+,}+a%$-1=}%$
.J - 37 char
Lê de stdin, produz para o console.
1!:1]3
é a chamada para stdin.tolower;._2
executa 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 iniciaisdlb
.fonte
JavaScript (ECMAScript 6) -
148139135 caracteresVersão 2:
Atualizado para usar a compreensão da matriz:
Versão 1:
Assume que:
s
;Com comentários:
Se você quiser:
.join('')
-o no final;s
variável porprompt()
; ouf
e adicionef=s=>
ao início.Corrida:
Dá a saída:
fonte
/\s*/
a/ */
e removendo os parênteses em tornoj=0
...
vez deapply
?...
) é um que eu nunca encontrei antes.[].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``;
Perl - 46 bytes
Contando o shebang como 1. Esta é uma tradução simplificada da solução Ruby abaixo.
Ruby 1.8 - 72 bytes
A entrada é retirada de
stdin
.Uso da amostra:
fonte
/i
efor
.Python -
2062041991771451291179488 caracteresEu 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.fonte
f
o 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)]))
Ruby 1.9+, 51 (ou 58 ou 60)
Assume que tudo está em minúsculas. A diferenciação entre
.upcase
maiúsculas e minúsculas custa 7 caracteres via , enquanto a diferenciação entre maiúsculas e minúsculas custa 9 caracteres via.downcase
.fonte
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.
Ungolfed:
Solução:
fonte
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 curtocat(unlist(sapply(letters,function(i)rep(i,max(sapply(gregexpr(i,readLines(f)),function(x)sum(x>0)))))),sep="")
assumirf
o nome do arquivoHaskell,
109108O 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.
fonte
Perl 6:
5653 caracteres;5855 bytesPara cada linha, ela procura por caracteres não espaciais da string de caixa inferior (
comb /\S/,.lc
) e cria umaBag
ou uma coleção de cada caractere e quantas vezes ocorre.[∪]
leva a união dosBag
s 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 caracteresBag
replicados 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:
fonte
Haskell,
183 162159Supondo que o arquivo esteja dentro
file.txt
!Se file.txt contiver, por exemplo
O script exibirá
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 aOrd
instância de Strings funciona) e largo a letra que eu anexei no início, livre-me dos espaços e produzo o resultado.fonte
drop 1
, basta usartail
C, 99 caracteres
Falha se menos de uma nova linha for fornecida. Eu acho que poderia ser corrigido facilmente.
fonte
kdb (q / k): 59 caracteres:
-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.
fonte
Perl, 46
Aqui está outra solução Perl, lê STDIN, requer
-n
troca (+1 para contar), vincula-se à pontuação do primo, mas roda sem queixas :-). Explora o fato de queor
o resultado do bit a bit possui um comprimento maior do argumento da string.fonte
Estou adicionando minha própria solução:
Bash - 72
Assume que a entrada está no arquivo "i"
Explicação
Para cada letra possível, filtra-a apenas do arquivo de entrada, resultando em algo como isto:
Em seguida, o resultado é classificado e a linha mais longa é selecionada.
echo -n
existe para remover novas linhas.fonte
Bash,
171159158, 138 com saída de lixo eletrônicoRequer 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 quesplit
cria (xaa, xab ... xaz, ???).Em
bash
,{a..z}
saídasa b c d e f ...
.Saída de amostra
Explicação
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.
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ê.
Para cada letra,
$l
leia todas as linhas armazenadas nos arquivosxa$s
.Remova a
-s
opção para economizar 1 caractere e obter muita saída indesejada. Impedegrep
queixas sobre arquivos inexistentes (ocorrerão a menos que você tenha 26 linhas de entrada). Isso processa o arquivoxa$s
, removendo tudo menos ocorrências$l
e enviando saída para o arquivob$l
. Então "eu amo mamãe" se torna "mmm" com novas linhas após cada letra quando$l
é m.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
) ...... armazenar nosso novo registro no arquivo
$l
. No final desse loop, quando passamos por todas as linhas, o arquivo$l
armazenará x linhas cada uma contendo a letra$l
, onde x é o maior número de ocorrências dessa letra em uma única linha.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
tr
paraecho $l
, salvando 6 caracteres.fonte
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 .split _ -l1
e perceber que sua entrada está sendo salva-l1aa
, acho que sua versãosplit
não está sendo reconhecida-l1
como uma opção e, em vez disso, a considera um prefixo de saída . Tente colocar um espaço entre-l
e1
, ou colocar--lines=1
, ou apenas-1
(isso parece ser uma sintaxe obsoleta e com mais golfe, com a qual agora atualizarei a postagem).C #, 172 bytes
fonte
Python 2-129
Ideia de @Tal
Mais algumas maneiras de fazer a mesma coisa no mesmo número de caracteres:
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.
fonte
Mathematica v10-110
Ainda não saiu, mas lendo a nova documentação com muito cuidado, acho que isso deve funcionar:
fonte
Scala, 125 caracteres
Primeiro, li a entrada, convertendo-a em minúsculas e adicionando uma linha vazia.
Então, para cada letra de
a
atéz
eu 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:max
nã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
stdin
porfromFile("FILENAME")
, aumentando o tamanho do código para 132 caracteres + comprimento do nome do arquivo.fonte
Javascript, 261 caracteres
Remova
eval(...)
oe execute para obter o código real; isto é ( um pouco ) comprimido.s
multi-funções como a matriz de linhas e como a sequência de saída,h
contém o histograma das letras por linha eH
conté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 :)
fonte
@
até que eu cheguei ao fim. I like it :)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:fonte
PowerShell - 141
Lê o texto de um arquivo chamado 'a'.
fonte
Groovy,
113/127102/116 caracteresSupondo que o arquivo esteja em um único caso (102 caracteres):
Supondo que o arquivo esteja em maiúsculas e minúsculas (116 caracteres):
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.fonte
Bash (principalmente inábil) -
172163157O texto precisa ser canalizado para o awk (ou especificado como um arquivo).
Exemplo de entrada
Saída de exemplo
PHP (provavelmente poderia ser melhor) -
174210.Assume que a sequência está contida na variável $ s
Exemplo de entrada
Saída de exemplo
fonte
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:
Então você pode chamá-lo para qualquer string:
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:
Executar como:
Darei à você:
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.
fonte
K, 34
fonte
Python 2, 154 bytes
fonte
s
no final daimport
instrução e owith
bloco 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.C, 298 bytes
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?
fonte
int
deint main()
eint j,n;
.PHP, 143 bytes
Supondo que a entrada seja passada na variável
$s
: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:
fonte
Python (209, com a amostra incluída, 136 sem.):
Vou postar uma amostra de PYG esta tarde.
fonte