ETAOIN SHRDLU golf


43

Breve descrição do desafio:
baseado no ETAOIN SHRDLU , seu desafio é escrever o programa ou a função mais curto em qualquer idioma que produza as 26 letras do alfabeto inglês com base na frequência na entrada.

Especificação muito longa, seca e completa:

  • Seu programa / função receberá como entrada uma sequência de texto, que conterá uma ou mais letras maiúsculas e / ou minúsculas e também poderá conter pontuação, numerais, símbolos e outros caracteres não alfabéticos.
  • O programa / função deve produzir apenas as 26 letras maiúsculas do alfabeto inglês, incluindo as que não aparecem na entrada, ordenadas da mais para a menos frequente com base em quantas vezes elas aparecem na entrada.
  • Editar: a frequência é calculada sem distinção entre maiúsculas e minúsculas, mas a saída deve estar em maiúsculas.
  • Se duas ou mais letras tiverem a mesma frequência, elas podem estar em qualquer ordem.
  • Nenhuma outra saída, como espaço em branco, é permitida.
  • Editar 1/7/2014: com base nos comentários, estou alterando esta regra. A única outra saída permitida é o espaço em branco inicial e / ou final opcional, como uma nova linha final. Nenhuma outra saída é permitida.
  • Comportamento indefinido é permitido para entrada que não contém nenhuma letra.

O vencedor será escolhido daqui a sete dias, então digite os dedos!


Exemplo de entrada:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent vitae erat velit. Mauris gravida euismod libero ut tincidunt. Phasellus elit dui, consectetur et egestas in, aliquam vitae diam. Donec eget varius ante. Vestibulum cursus diam aliquet, egestas orci quis, placerat dolor. Proin vel nisi lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aliquam erat volutpat. Etiam libero tortor, ornare id dui eget, posuere dignissim libero. Pellentesque commodo consequat volutpat. Integer hendrerit sapien libero, vel viverra augue facilisis sit amet. Quisque consectetur eget nisl quis dignissim. Ut lacinia pretium quam a placerat.
Morbi sed interdum risus, nec pretium lectus. Morbi imperdiet est id accumsan molestie. Duis sed fermentum nisl. Nunc vitae augue mattis, dictum lectus vel, accumsan nisl. Sed ultricies adipiscing rhoncus. Vivamus eu lacus a enim venenatis eleifend. Praesent consectetur tortor non eleifend ultricies. Mauris et odio posuere, auctor erat at, fringilla est. Proin in vestibulum erat. Maecenas congue commodo ante vel varius. Sed tempus mi ut metus gravida, nec dictum libero dapibus. Morbi quis viverra elit. Ut pharetra neque eget lacus tincidunt dictum. Fusce scelerisque viverra tellus et pretium.
Fusce varius adipiscing odio. Nulla imperdiet faucibus sem, at rhoncus ipsum adipiscing vitae. Phasellus imperdiet congue lacus et mollis. Nullam egestas mauris magna, et mollis lectus varius ut. Sed sollicitudin adipiscing dolor, vel elementum elit laoreet molestie. Aliquam nec nulla vel sem ultrices ullamcorper. Nullam nec felis magna. Duis sodales orci non justo aliquam tempus. Integer mi diam, tempor sed vulputate et, varius et nunc. Vestibulum sodales ipsum id mi pharetra, ut convallis mi accumsan. Sed dictum volutpat vestibulum.
Quisque ac dolor sagittis, aliquam libero at, euismod enim. Nulla ullamcorper posuere nulla vitae varius. Nam at dolor non libero elementum pellentesque in in lorem. Fusce porttitor turpis in quam placerat varius. Donec lorem orci, condimentum eu sapien sit amet, aliquet commodo magna. Quisque sed lectus sit amet arcu euismod accumsan et non nunc. Phasellus placerat congue metus, feugiat posuere leo dictum quis. Sed ultricies feugiat eros dignissim bibendum.
Mauris scelerisque consectetur libero eget varius. Aenean neque nunc, ullamcorper vitae orci in, auctor ornare sapien. Nam lacinia molestie imperdiet. Nam vitae mattis nibh. Vestibulum consequat tellus ac nisi sagittis pulvinar. Nullam mollis ornare quam, et venenatis leo porttitor sit amet. Nulla urna neque, dignissim non orci ut, volutpat ultrices erat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque vestibulum tellus nec eros faucibus porta.

Exemplo de saída:

EITUSALNROMCDPVGQBFHJKWXYZ

Nota: existe um empate de 5 vias KWXYZpara essa entrada.

Editar:

A competição acabou! Obrigado a todos que participaram. E agora para o (s) vencedor (es): As respostas de Dennis 'CJam e Isaacg's Pyth chegaram com 19 caracteres impressionantes. (Desculpe, mas não vou aceitar nenhuma das respostas, porque acho que seria injusto com a outra.) Editar: Seguindo o conselho de Dennis, vou marcar sua resposta como aceita, porque foi a primeira a alcance 19 caracteres. Menções honrosas vão para a resposta Golfscript, de Ilmari Karonen, em terceiro lugar, com 22 caracteres, bem como a resposta Python de 75 caracteres, do undergroundmonorail, que obteve o maior número de votos. Mais uma vez, obrigado a todos que participaram!


A frequência é medida apenas para as letras maiúsculas da entrada?
Howard

2
@IlmariKaronen sim, as novas linhas contam como espaço em branco, de modo que não seria permitido.
Abraham Abraham

8
@Abraham: IMO; se uma nova linha à direita (especificamente) for permitida para alguns idiomas, geralmente deve ser permitida para todos os idiomas; não menos importante, porque um fluxo de texto deve ser finalizado por uma nova linha seguida por EOF.
Williham Totland 01/07/2014

3
@WillihamTotland com base no número de votos que seu comentário possui, modificarei as regras para permitir uma nova linha à direita.
Abraham Abraham

1
O que fazer se houver duas respostas com o código mais curto? sugere atribuir a marca de seleção verde à solução anterior. isaacg postou sua resposta primeiro, joguei a minha em 19 bytes primeiro. Qualquer que seja o desempate que você escolher será bom para mim, mas não ter uma resposta aceita é um pouco anti-climático na minha opinião.
Dennis

Respostas:


26

CJam, 21 19 bytes

qeu:A;'[,65>{A\-,}$

Experimente online.

Exemplo

$ cjam etaoin.cjam <<< "~XyxY YyxZ"
YXZABCDEFGHIJKLMNOPQRSTUVW

(sem nova linha)

Como funciona

qeu:A; " Read from STDIN, convert to uppercase, save in the variable “A” and discard, ";
'[,    " Push an array of all ASCII characters before “[” (NUL to “Z”).               ";
65>    " Remove the first 64 characters (NUL to “@”).                                 ";
{      " Sort the array of characters by the following mapping:                       ";
  A\   " Swap the character with the string saved in variable “A”.                    ";
  -    " Remove all occurrences of the character from the string.                     ";
  ,    " Push the length of the string.                                               ";
}$     "                                                                              ";

Mais ocorrências significa que mais caracteres são removidos; portanto, os caracteres mais frequentes aparecem no início da matriz.


Muito esperto mesmo.
Abraham Abraham

Parabéns @Dennis por vencer o concurso!
Abraham

43

Python 2 ou 3 - 77 75 bytes

f=lambda s:''.join(sorted(map(chr,range(65,91)),key=s.upper().count))[::-1]

Eu tive uma resposta antes que pegou a entrada do STDIN, mas percebi que era tecnicamente inválida. Eu usei o input()que obtém apenas uma única linha, mas o exemplo de entrada da pergunta implica que ele deve lidar com várias linhas ao mesmo tempo. Para atender às especificações, transformei minha resposta em uma função que recebe um argumento de string. Para minha surpresa, era dois bytes menor! Não me ocorreu isso print(...)e input()foi mais longo que f=lambda s:e s.

Isso também torna a resposta compatível com o Python 2 e o Python 3. Originalmente, era apenas o Python 3, porque era usado input()(que foi chamado raw_input()em 2). Agora que é uma função, funciona em ambas.

Explicado

                                  range(65,91)                              # The numbers 65 to 90
                          map(chr,range(65,91))                             # Convert to ASCII

                                                    s                       # The input string
                                                    s.upper()               # Convert to uppercase
                                                    s.upper().count         # Function literal for 'how many times the argument appears in the string'

                   sorted(map(chr,range(65,91)),key=s.upper().count)        # Sort by that function
           ''.join(sorted(map(chr,range(65,91)),key=s.upper().count))       # Concatenate to string
           ''.join(sorted(map(chr,range(65,91)),key=s.upper().count))[::-1] # Step through by -1 (i.e. reverse string)

  lambda s:''.join(sorted(map(chr,range(65,91)),key=s.upper().count))[::-1] # Make it a function (`return` is implicit for lambdas)
f=lambda s:''.join(sorted(map(chr,range(65,91)),key=s.upper().count))[::-1] # Give it a name

2
Por outro lado, os comentários na explicação me fazem facepalm. Bem-vindo ao CS 101!
Izkata 02/07/2014

6
@ Izkata O importante é que ele mostra em que ordem para ler o código. Porque o melhor lugar para começar a ler código de golfe raramente é óbvio, especialmente quando fica um pouco mais complicado ou conciso do que isso.
Martin Ender

1
Bela apresentação!
Xnor

3
@ Izk Meu objetivo era torná-lo compreensível para pessoas que não conhecem python. Eu nunca faria comentários como esses em um projeto real.
Undergroundmonorail

2
@imm No. countnão é uma variável nem nada, é uma função literal. Por mais legal que seja, poder multiplicar o valor de retorno de uma função -1colocando um -na frente, esse não é um recurso que o python possui.
Undergroundmonorail

15

Bash, 65 bytes

(tr a-z A-Z;echo {A..Z})|fold -1|sort|uniq -c|sort -nr|tr -dc A-Z

Exemplo

$ bash etaoin.sh <<< "~AbaB BbaC"
BACZYXWVUTSRQPONMLKJIHGFED

Como funciona

(              #
  tr a-z A-Z   # Turn lowercase into uppercase letters.
  echo {A..Z}  # Print all uppercase letters.
) |            #
fold -1 |      # Split into lines of length 1.
sort |         # Sort those lines (required for piping to uniq).
uniq -c |      # Print the frequencies of all lines.
sort -nr |     # Sort by frequency (reversed).
tr -dc A-Z     # Remove everything that's not an uppercase letter.

1
Esse local não é portátil, você precisa forçar LC_COLLATE = C (ou mais curto, LC_ALL).
Chris Baixo

6
A Portabilidade @ChrisDown geralmente não é uma preocupação nas respostas do código de golfe.
Kevin

1
Sem portabilidade, o que essa resposta faz não está bem definido.
21414 Chris Chris Down

@ ChrisDown: testei algumas seqüências de caracteres e alguns códigos de idioma, mas não consegui encontrar um exemplo em que o uniq se comporte incorretamente com caracteres alfabéticos. Você poderia me mostrar uma?
Dennis

@ChrisDown Este script é portátil o suficiente para rodar no OpenBSD usando as versões BSD de fold, sort, tr, uniq, se o shell for bash ou ksh93. Outros shells, como o zsh, não conseguem se expandir {A..Z}. Todos os códigos de idioma LC_COLLATE funcionam, porque o OpenBSD possui apenas LC_COLLATE = C.
kernigh

12

Pitão 1.0.2 , 19 20

=ZUwsVm;dSm[cZkk)UG

Experimente aqui: http://ideone.com/fork/YlWpEJ

Saiba mais sobre Pyth aqui: http://esolangs.org/wiki/Pyth

Exemplo:

Baseado no ETAOIN SHRDLU, seu desafio é escrever o programa ou a função mais curta em qualquer idioma que produza as 26 letras do alfabeto inglês com base em sua frequência na entrada.

Dá:

TENOHARSIULGFPYDCBWQMZXVKJ

Explicação:

=ZUw: Converta entrada para maiúscula e armazene em Z.

sV: Imprima a soma do reverso de

m;d: As últimas entradas de

S: Classificados pela primeira entrada, em ordem crescente

m[cZkk): As listas [contagem de k em Z, k]

UG: Para k nas letras maiúsculas.

Equivalente em Python aproximado:

G='abcdefghijklmnopqrstuvwxyz'
Z=copy(upper(input()))
print(_sum(rev(_map(lambda d:d.pop(),sorted(_map(lambda k:_list(count(Z,k),k),upper(G)))))))

Isso não é entrada, eu apenas pensei que as pessoas gostariam de vê-lo. No Pyth 1.0.4, o programa a seguir é uma solução em 10 caracteres:

JUwo_cJNUG

Explicação:

JUw: Converter entrada em maiúsculas e armazenar em J.

o: (Imprimir) Classificar por

_cJN: -1 * (contagem de N em J)

UG: Acima de N nas letras maiúsculas.

Não é uma solução legal porque várias das alterações do Pyth 1.0.2 para 1.0.4, incluindo a adição da função oclassificar por, foram em resposta a esse problema.


Sugiro que você atualize o link Pyth para a página oficial do Pyth, se ele existir.
AL

@AL Essa é a página oficial do Pyth, até que eu coloquei uma entrada esolang.
Isaacg 01/07

Por que você precisa armazenar a entrada em uma variável Zpara se referir a ela mais tarde? Apenas colocar a expressão Zem seu lugar faria com que a entrada fosse lida várias vezes?
Xnor

@xnor A posição em que Z é usada está dentro de uma função lambda, porque está no primeiro argumento de um mapa e, portanto, precisa ser salva em uma variável. O uso de Uw resultaria na leitura de entrada 26 vezes.
Isaacg 01/07

1
@AL Tudo bem, Pyth está no esolang e no github. O link do github está na parte inferior da página esolang, que está vinculada na resposta. O Github codifica a colorização.
Isaacg

11

Javascript ( ES6 ) 119 117

Edit: (-2) Removida a necessidade de toUpperCaseusar um RegEx que não diferencia maiúsculas de minúsculas na splitchamada.

a=prompt(f=x=>a.split(RegExp(x,'i')).length)
alert([...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'].sort((b,c)=>f(c)-f(b)).join(''))

Alternativa (mesmo comprimento): Condensou a classificação e a contagem de caracteres em uma única função.

a=prompt()
alert([...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'].sort(f=(b,c)=>c?f(c)-f(b):a.split(RegExp(b,'i')).length).join(''))

Em função: 105 104

Edit: (-1) Condensou a classificação e a contagem de caracteres em uma única função.

F=a=>[...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'].sort(f=(b,c)=>c?f(c)-f(b):a.split(RegExp(b,'i')).length).join('')

1
Técnica interessante.
Matt

1
Salpicar uma corda ... delicioso!
Bergi 01/07/2014

10

GolfScript, 22 caracteres

:?91,+-26>{.32+]?\-,}$

Experimente online.

Explicação:

  • :?atribui a sequência de entrada ao símbolo ?. (Eu uso um símbolo de pontuação para que o número a seguir 91não seja analisado como parte do nome do símbolo.)
  • 91,constrói uma lista dos números de 0 a 90 (código ASCII de Z).
  • + anexa esta lista à string de entrada, convertendo-a de uma matriz de códigos ASCII em uma string (e também removendo convenientemente a string de entrada da pilha).
  • -26>pega os últimos 26 caracteres dessa sequência, produzindo uma sequência contendo as letras ASCII maiúsculas de Aaté Z.
  • O { }$aplica o bloco de código a todos os caracteres na sequência de entrada e classifica esses caracteres de acordo com o resultado.
  • Dentro do bloco de código, .duplica o caractere e 32+converte a cópia de maiúscula para minúscula. Ele ]coleta esses dois caracteres em uma matriz, ?\-pega a cadeia de entrada armazenada ?e remove todas as ocorrências dos caracteres da matriz e ,conta o comprimento da cadeia restante, que será a chave de classificação. Os caracteres serão classificados em ordem crescente por essa chave e, portanto, em ordem decrescente por número de ocorrências.

1
Parece que tivemos a mesma ideia. Bug menor: falta a letra Z. Deveria ser 91,+-26>.
Dennis

@ Dennis: Ah, oops. Corrigido, embora quem precise dessa carta, afinal? :)
Ilmari Karonen

2
@IlmariKaronen Com base nos comentários da comunidade, alterei as regras para permitir uma nova linha à direita (consulte a pergunta para uma descrição completa). Sua pontuação é agora 22, mais do que 25:)
Abraham

8

Haskell, 110 bytes

import Data.List
import Data.Char
a%f=compare(f a).f
f t=sortBy(% \c->length$filter((/=c).toUpper)t)['A'..'Z']

Exemplo de uso:

λ> f "Based off ETAOIN SHRDLU, your challenge is to write the shortest program or function in any language that outputs the 26 letters of the English alphabet based on their frequency in the input."
"ETNAHORISULFGPBCDYMQWJKVXZ"

1
Que tal (/=c)e se livrar do 0-?
Lynn

@Mauris captura agradável! Eu editei e raspei outro personagem.
Flonk

6

Ruby 2.0, 53 caracteres

EDIT : corrigido para funcionar corretamente com seqüências de linhas múltiplas, obrigado @ durron597!

f=->s{$><<(?A..?Z).sort_by{|c|-s.upcase.count(c)}*''}

Cria uma função chamada fque pode ser usada da seguinte maneira:

f['jackdaws love my big sphinx of quartzzz']

Imprime em STDOUT:

AZOSICGHEJKLMBFPQRDTUVWXYN

2
Esta resposta não está correta. Dá esta resposta: EITASUROLNCMPDVQGBHFKJWXYZpara o exemplo na pergunta
durron597

1
@ durron597 Obrigado, você está correto! Ele não estava lidando com seqüências multilinhas corretamente - getsretorna uma linha de cada vez. Pode ser corrigido alterando getspara, gets$nmas alterá-lo para uma função é 1 char mais curto.
Paul Prestidge

6

Perl, 54 46 bytes

UPDATE: após otimizações adicionais, ele pode ser compactado para 46 bytes: (thx dennis para -n/ {}hack; chinês perl goth para <=>-> -hack)

s/./$h{uc$&}++/eg}{say sort{$h{$b}-$h{$a}}A..Z

É para ser executado com run com perl -nE

Solução original (não precisa de opções especiais de Perl):

s/./$h{uc$&}++/egfor<>;print sort{$h{$b}<=>$h{$a}}A..Z

Verificado no Perl 5.8.3, 5.14.2

Se você receber um aviso, separe ege forcom um espaço (+1 caractere), se você se importar

exemplo de uso:

$ python -c 'import this' | perl -le 's/./$h{uc$&}++/egfor<>;print sort{$h{$b}<=>$h{$a}}A..Z' 2>/dev/null
ETAISONLRHPBUCDYMFGXVWKZJQ

EXPLICAÇÃO: Em cada caractere ( .) de cada linha de entrada ( for<>), aplique uma substituição "padrão", que de fato é avaliada como uma expressão ( esinalizador de s///), que incrementa um uccaractere upcased ( ) ( ./ $&é menor que o mais óbvio (.)/ $1) contam no hash (não inicializado) ( %h). Em seguida, o hash da frequência da letra é usado em uma função de comparação de classificação para imprimir o alfabeto maiúsculo na ordem correta.


1
Mensagens mais curtas e sem erro:perl -ne 's/./$h{uc$&}++/eg}{print sort{$h{$b}<=>$h{$a}}A..Z'
Dennis

Dennis: muito interessante, parece um erro de digitação .. o que é isso? Eu tive algumas variantes usando -ne END{}, mas eles sempre foram mais .. sinta-se livre para atualizar a resposta, se você quiser
mykhal

1
Sim, -nenvolve while(<>){...}o código. Evito editar o código de outros usuários. Muito fácil cometer um erro, algumas coisas só funcionam em alguns computadores, etc.
Dennis

1
Joe: eu estava falando sobre a }{"injeção", não apenas sobre a -nopção bem conhecida . Uma não pode esperar que a cadeia de código realmente tecnicamente é envolto pela enquanto seqüência de código de loop antes da execução, não só apenas que de alguma forma funciona como como se estivesse envolto ..
mykhal

1
salvar mais dois caracteres: substituir $h{$b}<=>$h{$a}com$h{$b}-$h{$a}
perl chineses goth

5

R, 123 bytes

O código foi aprimorado graças às sugestões de @RichieCotton.

text <- "Based off ETAOIN SHRDLU, your challenge is to write the shortest program or function in any language that outputs the 26 letters of the English alphabet based on their frequency in the input."

f=function(x){b=plyr::count(toupper(strsplit(x,"")[[1]]));c=merge(LETTERS,b,all.x=T);paste(c[order(-c$freq),1],collapse="")}

f(text)

Resultado:

> f(text)
[1] "ETNAHORISULFGPBCDYMQWJKVXZ"

1
@ RichieCotton: Rejeitei sua edição sugerida duas vezes agora. Não sei se você é notificado com o motivo da rejeição da votação. Portanto, se você ler o seguinte: forneça melhorias nos comentários nos comentários para que o OP possa analisá-los. Aqui está o porquê: meta.codegolf.stackexchange.com/a/1619/8478
Martin Ender

4

C ++, 185 183 179 177 bytes

Não se espera que ganhe, é claro (o C ++ pode vencer?), Mas mesmo assim é um exercício divertido.

#include <algorithm>
#include <stdio.h>
int f[256],p;main(){for(p=65;p<91;p++)f[p]=p;while(~(p=getchar()))f[p&95]+=256;p=256;std::sort(f,f+p);while(p--)f[p]&95&&putchar(f[p]);}

Explicação:

#include <algorithm>         // for std::sort
#include <stdio.h>           // for getchar, putchar
int f[256],p;                // declare an array of count-prefixed chars, and a counter
main(){
    for(p=65;p<91;p++)       // 65 == 'A', 91 == the character after 'Z'
        f[p]=p;              // set the character for the slot
    while(~(p=getchar()))    // read characters until EOF
        f[p&95]+=256;        // increment the packed count for the character stripped of the 'lowercase bit'
    p=256;                   // start a countdown
    std::sort(f,f+p);        // sort the array
    while(p--)               // do the countdown
        f[p]&95 &&           // if the masked-off character is set...
          putchar(f[p]);     // print it
}

4

VBScript 181 109

Atualizado para usar um algoritmo completamente diferente. Bate JavaScript!

Bonita:

dim b(99):i=ucase(inputbox(k))
for y=65to 90
    c=chr(y)
    a=len(replace(i,c,k))
    b(a)=c+b(a)
next
msgbox join(b,k)

Golfe:

dim b(99):i=ucase(inputbox(k)):for y=65to 90:c=chr(y):a=len(replace(i,c,k)):b(a)=c+b(a):next:msgbox join(b,k)

4

J 41 35 Bytes

(u:65+i.26)([\:[#/.~@,e.~#])toupper

Demo:

i=: 'This is a test to see whether this is still working'
(u:65+i.26)([\:[#/.~@,e.~#])toupper i
STIEHLORWAGKNBCDFJMPQUVXYZ

Explicação:

(u:65+i.26) & ( [ \: [ #/.~@,e.~#]) toupper) )
ABCDE...          |    |    |   |      uppercase the right argument
                  |    |    |   \copy from right only member from left
                  |    |     \append the left argument
                  |    \ Afterwards Count apperances of each letter
                  \ Sort the left according to the appearances

A chave é anexar a matriz esquerda, de modo que todas as letras estejam disponíveis e já em ordem. Uma conseqüência engraçada do uso de um substantivo como terceiro dente no garfo é que ele funciona tanto como verbo quanto como frase.


4

Groovy - 130 123 115 112 98 92

Conforme o conselho do @ cfrick (duas vezes!):

f={('A'..'Z').collectEntries{c->[c,it.grep(~/(?i)$c/).size()]}.sort{-it.value}*.key.join()}

Um pequeno teste (roubado descaradamente de @jpjacobs):

assert f('This is a test to see whether this is still working') == 
    'STIEHLORWAGKNBCDFJMPQUVXYZ'

E o teste proposto também está passando


1
A função precisa gerar todas as 26 letras, não apenas as presentes na sequência de entrada.
algorithmshark

@algorithmshark, na verdade, o meu erro, fixa
Will Lp

f={('A'..'Z').collectEntries{c->[c,it.toUpperCase().findAll(c).size()]}.sort{-it.value}.keySet().join()}para 104
cfrick

1
outros 6 bytes: em it.grep(~/(?i)$c/)vez deit.toUpperCase().grep(c)
cfrick 04/07

@cfrick Wow! Obrigado novamente! Que toUpperCaseestava incomodando o inferno fora de mim.
Will Lp

4

SAS - 217 (eu acho)

A entrada deve ser colocada na linha após a instrução cards4 ou nos cartões perfurados apropriados para o seu sistema. Eu acho que essa abordagem salva alguns caracteres vs. a tentativa de citar a entrada.

data a;
input;
S = upcase(compress(_INFILE_,,'ak'));
do i=1 to length(S);
l=substr(S,i,1);
output;
end;
cards4;
;;;;
run;
proc sql;
select l into :o separated by '' from
(select l, 1/count(l) as f from a group by l) order by f;
quit;

Estou ciente de que isso não atende à especificação completa, pois retorna apenas caracteres que aparecem na string de entrada. Talvez eu precise repensar isso um pouco.


Não atende às especificações, mas ainda é legal, então +1: D
cat

4

AppleScript, 278

Notei que isso "a" = "A"é verdade no AppleScript. Eu posso usar isso no código golf, mas o restante do script é muito prolixo. Eu usei o AppleScript 1.8.3.

Isso define uma função f. Se você adicionar f("a string")na parte inferior do script e executá-lo no Editor de Script, ele mostrará o resultado.

on c(n)
ASCII character(64+n)
end
on f(s)
set{a,r}to{{},""}
repeat with i from 1 to 26
set j to 0
repeat with b in s
if b&""=c(i)then set j to j+1
end
set a to a&j
end
repeat with j from 0 to(count s)
repeat with i from 1 to 26
if a's item i=j then set r to c(i)&r
end
end
r
end

Formatado e comentado:

-- Returns nth letter of alphabet.
on c(n)
    ASCII character (64 + n)
end c

-- Returns letters in s sorted by frequency.
on f(s)
    -- a: list of letter counts
    -- r: resulting string
    set {a, r} to {{}, ""}

    -- For each letter from A to Z,
    -- count letters in string s.
    repeat with i from 1 to 26
        set j to 0
        repeat with b in s
            -- Can't use b = c(i), because
            -- b is a reference to a string
            -- and = never dereferences its
            -- operands. Get contents of b,
            -- here by coercing b to string.
            if b & "" = c(i) then set j to j + 1
        end repeat
        -- Set item i of a to count j.
        set a to a & j
    end repeat

    -- Sort letters by frequency.  Do a counting sort
    -- because AppleScript lacks a sort command.
    repeat with j from 0 to (count s)
        repeat with i from 1 to 26
            if a's item i = j then set r to c(i) & r
        end repeat
    end repeat
    r
end f

-- Example call:
f("Now is the time for all good men to come to the aid of their country.")
-- Result: "OTEIRNMHLFDCAYWUSGZXVQPKJB"

3

VBScript 157 156 bytes

Edit: alterado msgbox (p) para msgbox p

Mais legível:

s=ucase(InputBox(z))    'z is empty.
L=len(s)
Dim a(255)
for i=1to L
    x=asc(mid(s,i))
    a(x)=a(x)+1
next
for t=0to L
    For i=65To 90
        If a(i)=t then p=chr(i)&p
    next
next
msgbox p

Golfe: (155 caracteres + 1 retorno de carro)

s=ucase(InputBox(z)):L=len(s):Dim a(255):for i=1to L:x=asc(mid(s,i)):a(x)=a(x)+1:next:for t=0to L:For i=65To 90:If a(i)=t then p=chr(i)&p
next:next:msgbox p

Eu o tinha no início 171, com um código que achei mais interessante, mas o método de classificação de confortavelmente o drei é mais curto e requer len (s), o que torna um "for" mais curto que o "while" para o primeiro loop. (bocejar)

's=UCase(InputBox(Z))&8 'just need any extra character.  0-7 don't work because &7 is octal

s=UCase(InputBox(Z)) 'nevermind
Dim a(999)
While Len(s)
    x=Asc(s) 'returns ascii of first char
    a(x)=a(x)-1 'going negative saves a character later...
    s=Mid(s,2) 'doesn't care if you run out of string
Wend
for j=1 to 26 'this used to be   While Len(p)<26
    For i=65To 90
        If a(i)<a(y) Then y=i 'it is barely not worth it to do a(i)+a(i+32)>a(y) here to skip the ucase() above
    Next
    p=p&Chr(y)
    a(y)=1 'if I didn't go negative this would have to be -1.  arrays default to 0.
Next
MsgBox(p)

Eu aprendi alguns truques legais deste post! Obrigado pela menção também. Uma coisa: acho que for t=0deveria for t=1, caso contrário você sempre imprime o alfabeto inteiro.
Confortavelmenterei

1
@comfortablydrei É necessário imprimir o alfabeto inteiro. "O programa / função deve produzir apenas as 26 letras maiúsculas do alfabeto inglês, incluindo as que não aparecem na entrada"
JesterBLUE 01/07/14

Uau. perdeu aquele. então é meu erro. obrigado!
Confortavelmenterei

3

J - 38 35 char

Uma função que recebe entrada à direita como uma string. Não é um vencedor, mas foi divertido escrever.

(u:65+i.26)([\:[#/.~@,e.~#])toupper

Explicado:

  • toupperé um verbo na biblioteca padrão que contém uma string. Isso então se torna o argumento correto do verbo, enquanto o argumento esquerdo é o alfabeto: o código ASCII aponta 65 a 90.

  • [e ,e.~#])seleciona ( #) as letras no argumento à direita ( ]) que são elementos de ( e.~) à esquerda e depois adiciona ( ,) o argumento à esquerda ( [). A saber, mantemos apenas os caracteres maiúsculos e adicionamos uma única cópia do alfabeto ao final, para garantir que todos sejam capturados.

  • #/.~@depois fornece as frequências de cada caractere. Acontece que isso é dado em ordem alfabética; logo depois, podemos separar ( \:) o alfabeto (o argumento da esquerda [).

Um exemplo rápido e preguiçoso abaixo. Sinta-se livre para experimentá-lo para si mesmo em tryj.tk .

   (u:65+i.26)([\:[#/.~@,e.~#])toupper 'Based off ETAOIN SHRDLU, your challenge is to write the shortest program or function in any language that outputs the 26 letters of the English alphabet based on their frequency in the input.'
ETNAHORISULFGPBCDYMQWJKVXZ

3

T-SQL 178

Basicamente, esta é minha solução VBScript, mas implementada em SQL.

Isso é abuso de saída XML para concatenar uma coluna. Em uso prático, ele pode ser associado a uma tabela externa para emular GROUP_CONCATfunções no MySQL e outras.

Declarando a @variável:

DECLARE @ CHAR(1024)= 'enter your text here';

Código:

with y AS(
    SELECT UPPER(@)i,0l,91y
    UNION ALL
    SELECT i,len(replace(i,char(y-1),'')),y-1
    FROM y
    WHERE y>65
)
SELECT LTRIM(
(
    SELECT char(y)
    FROM y
    WHERE y<91
    ORDER BY l
    FOR XML PATH(''))
)

3

Perl, 78 bytes

undef$/;$i=<>;$r{$i=~s/$_//gi}.=$_ for A..Z;print$r{$_}for sort{$b<=>$a}keys%r
  • Somente as 26 letras ASCII maiúsculas sem nenhum espaço em branco são exibidas em ordem de frequência.
  • Os caracteres vinculados são dados em ordem alfabética.

Resultado para o exemplo na pergunta:

EITUSALNROMCDPVGQBFHJKWXYZ

Ungolfed:

# read input
# ----------
undef $/; # disable input separator
$i = <>;  # $i holds the complete input as one string

# analyze
# -------
# For each uppercase letter (A upto Z) its occurences are counted
# via the number of substitutions made by s/$_//gi. The lowercase
# letter is included via modifier "i".
# 
# The occurrence count is then used as key for hash %r.
# The uppercase letter is appended to the value of that hash entry.
$r{$i =~ s/$_//gi} .= $_ for A..Z;

# output
# ------
# The hash keys are sorted numerically in reverse order by
# the specified sort function.
print $r{$_} for sort {$b<=>$a} keys %r

Isso pode funcionar por exemplo, bot, não por exemplo, para echo -e 'x\ny\n\nz\n'saída, que deve retornar XYZABCDEFGHIJKLMNOPQRSTUVW, mas gera XYABCDEFGHIJKLMNOPQRSTUVWZ. Adivinha o porquê .. :)
mykhal

@mykhal: Fixed.
Heiko Oberdiek

3

PHP - 105 bytes

<?preg_filter(~‹§æ“Ö¢‹ö,'$f[$0&fl]++',join('',range(a,z)).$argv[1]);arsort($f);foreach($f as$l=>$F)echo$l;

Aqui está um hexdump, causa dos caracteres especiais:

0000000 3c 3f 70 72 65 67 5f 66 69 6c 74 65 72 28 7e dc
0000010 a4 be d2 85 a2 dc 9a 2c 27 24 66 5b 24 30 26 df
0000020 5d 2b 2b 27 2c 6a 6f 69 6e 28 27 27 2c 72 61 6e
0000030 67 65 28 61 2c 7a 29 29 2e 24 61 72 67 76 5b 31
0000040 5d 29 3b 61 72 73 6f 72 74 28 24 66 29 3b 66 6f
0000050 72 65 61 63 68 28 24 66 20 61 73 24 6c 3d 3e 24
0000060 46 29 65 63 68 6f 24 6c 3b                     
0000069

E uma versão um pouco menos golfe:

<?
preg_filter(           // regular expression
  "#[A-z]#e",          // matches every letter + 'eval' flag
  '$f[$0&fl]++',        // so this code runs for every letter
                       // $f is an array whose indices are uppercase letters
                       //   and whose values represent the number of occurences
                       // lowercase is converted to uc with the bitwise and
                       //   fl is 11011111 in binary, every bit except for 32's is set
  join('', range(a,z)) // adding abcdefghijklmnopqrstuvwxyz to the input
    .$argv[1]);        //   because not all letters have to appear in the input
arsort($f);            // sort $f in reverse, maintaining indices
foreach($f as$l=>$F)   //
  echo$l;              // print each index in order

Exemplo:

 $ php etaoin_shrdlu.php "This function sorts an array such that array indices maintain their correlation with the array elements they are associated with."
 ATIRESHNOCYUWMDLFXZBVGPQKJ

Como funcionam os caracteres especiais preg_filter()?
Abra Abraham

3
No PHP ~ é o operador NOT bit a bit, e você pode aplicá-lo também a strings, caso em que funciona em todos os caracteres. Além disso, o PHP tem prazer em analisar cadeias de texto como literais, já que não há caracteres especiais (por exemplo, operadores, $ para variáveis, ponto-e-vírgula, parênteses ...). Assim, escrever ~ ‹§æ“ Ö ¢ ‹ö (a versão invertida bit a bit) em vez de" # [Az] #e "economiza um byte, pois não precisa ser citado.
Aurel Bílý

Ah obrigada. Faz sentido agora.
Abra Abraham

1
Na medida em que tudo no PHP faz sentido. Santo Moly.
fofo

echo join(array_keys($f));pode salvar um byte
Titus

3

C # no LINQPad - 203 bytes

Adotei uma abordagem diferente da resposta de Logan Dam. Primeiro, certifiquei-me de que cada caractere na sequência de entrada seja classificado por sua aparência e só exista uma vez na sequência de saída. Depois disso, adicionei todos os caracteres ausentes do alfabeto à string de saída.

void e(string i){var a="";foreach(var d in i.ToUpper().GroupBy(x=>x).OrderByDescending(u=>u.Count()))if(d.Key<91&&d.Key>64){a+=d.Key;}for(int x=65;x<91;x++)if(!a.Contains((char)x)){a+=(char)x;}a.Dump();}

Infelizmente, não superaria a resposta de Logan Dam se eu tivesse feito no Visual Studio.

Versão mais legível:

void e(string i)
    {
        var a = "";
        foreach (var d in i.ToUpper().GroupBy(x => x).OrderByDescending(u => u.Count()))
        {
            if (d.Key < 91 && d.Key > 64)
            {
                a += d.Key;
            }
        }
        for (int x = 65; x < 91; x++)
        {
            if (!a.Contains((char)x))
            {
                a += (char)x;
            }
        }
        a.Dump();
    }

Yay, mais amor LINQ! : D
ldam

3

C # (e LINQ) 255 226 210 bytes

Usando o conselho de Patrick Huizinga, a sintaxe da consulta agora é mais curta:

namespace System.Linq{class P{static void Main(string[]a){Console.Write((from c in(a[0]+"ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper()where c>'@'&&c<'['group c by c into g orderby-g.Count()select g.Key).ToArray());}}}

Explicação:

Console.Write(
    (from c //declare our range variable
       in (a[0] + "ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper() //declare the datasource
     where c > '@' && c < '[' //include only letters
     group c by c into g //run of the mill group by
     orderby -g.Count() //order by descending
     select g.Key //we only want the actual letters
     ).ToArray() //mash it all into an array
  );

Sintaxe do método equivalente (217):

namespace System.Linq{class P{static void Main(string[]a){Console.Write((a[0]+"ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper().GroupBy(c=>c).OrderBy(c=>-c.Count()).Where(c=>c.Key>'@'&&c.Key<'[').Select(c=>c.Key).ToArray());}}}

Post original:

namespace System.Linq{class P{static void Main(string[]a){(a[0]+"ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper().GroupBy(c=>c).OrderByDescending(c=>c.Count()).Where(c=>c.Key>'@'&&c.Key<'[').ToList().ForEach(c=>Console.Write(c.Key));}}}

Esta é a minha primeira submissão e eu deveria estar fazendo as coisas no trabalho, mas isso parecia muito divertido, porque eu senti que poderia realmente participar pela primeira vez.

Explicação:

(a[0] + "ABCDEFGHIJKLMNOPQRSTUVWXYZ") //ensure each character appears once
  .ToUpper()
  .GroupBy(c => c) //get access to .Count()
  .OrderByDescending(c => c.Count())
  .Where(c => c.Key > '@' && c.Key < '[') //exclude anything other than letters
  .ToList() //Only lists have a .ForEach() :(
  .ForEach(c => Console.Write(c.Key)); //print output

Eu nunca uso a sintaxe do método para LINQ, então essa foi uma experiência de aprendizado para mim :) também pensando nisso agora, eu poderia economizar 2 bytes substituindo os literais de caracteres por seus equivalentes inteiros, mas, meh.

Encurtado graças às dicas de ProgramFOX e Num Lock :)

A sintaxe de consulta equivalente (um pouco mais longa):

(from c in (a[0]+"ABCDEFGHIJKLMNOPQRSTUVWXYZ").ToUpper() where c>'@'&&c<'[' group c by c into g orderby g.Count() descending select g.Key).ToList().ForEach(c=>Console.Write(c));

1
Em uma primeira olhada, você pode salvar muitos caracteres nomeando sua classe apenas em Pvez de Programe em string[]avez de string[] argse em c=>...vez de (c)=>....
Num Lock

Em vez de duas usinginstruções, você também pode colocar sua classe dentro do System.Linqespaço para nome e remover as duas usando instruções. Depois, você pode salvar alguns caracteres e ele ainda funcionará bem.
ProgramFOX

@NumLock Certo, nem pensei nisso :) @ProgramFOX que não vai me salvar nada porque namespaceé mais longo do que usinge os dois {}s extras me custam mais.
ldam

1
namespace System.Linq{}é claramente mais curto do que using System;using System.Linq;apenas olhando para ele. A idéia é omitir os dois usingcompletamente.
Num Lock

Ahh sim ele remove os dois, você está certo, eu estava pensando que apenas removeu o. Obrigado.
ldam

3

C ++ 701 322 232 bytes

Primeira versão 701 bytes (uso de STL idiomático)

#define _HAS_TRADITIONAL_STL 1
#include <numeric>
#include <iostream>
#include <iterator>
#include <string>
#include <algorithm>
#include <functional>
#include <map>
#include <set>
#define ALL(x) x.begin(), x.end()
using namespace std;
typedef istream_iterator<char> iic;typedef pair<int, char> pic;map<char, int> c;set<pic> d;
void f1(char x) {c[x]--;}
void f2(const pic &p) {d.insert(make_pair(p.second, p.first));}
int main(){string s(26, 0);stdext::iota(ALL(s), 65);copy(ALL(s), ostream_iterator<char>(cout));transform(iic(cin), iic(), back_inserter(s), toupper);for_each(ALL(s), f1);for_each(ALL(c), f2);transform(ALL(c2), ostream_iterator<char>(cout), select2nd<pic>());}

Versão limpa expandida:

#define _HAS_TRADITIONAL_STL 1
#include <numeric>
#include <iostream>
#include <iterator>
#include <string>
#include <algorithm>
#include <functional>
#include <map>
#include <set>
using namespace std;

typedef istream_iterator<char> iic;
map<char, int> counts;
set<pair<int, char> > counts2;

void docount(char ch) { counts[ch]--; }
void toCounts2(const pair<char, int> &p) { counts2.insert(make_pair(p.second, p.first)); }

int main()
{
    string s(26, 0);
    stdext::iota(s.begin(), s.end(), 65);
    transform(iic(cin), iic(), back_inserter(s), toupper);
    for_each(s.begin(), s.end(), docount);
    for_each(counts.begin(), counts.end(), toCounts2);
    transform(counts2.begin(), counts2.end(), ostream_iterator<char>(cout), select2nd< pair<int, char> >());
}

A idéia é demonstrar um programa C ++ "adequado" sem hacks. Ignore o clichê e o fato de que isso só é compilado no VC ++

Explicação:

Nós preenchemos A a Z em uma string com iota () , isso garante que, quando contamos as ocorrências, cada caractere apareça mesmo que não esteja na entrada.

transform () copia caractere por caractere da entrada padrão e o coloca no final de s após chamar toupper () em cada um

A contagem de cada caractere é diminuída no mapa (mantendo a contagem negativa, podemos ter uma classificação decrescente sem código extra)

As entradas do mapa de contagens são copiadas para um conjunto de pares, trocando (char, count) por (count, char). Como os conjuntos são ordenados, os classificamos diminuindo a contagem de frequências

Por fim, copiamos o conteúdo do conjunto para padronizar, usando transform e select2nd () para selecionar apenas o segundo membro do par.

O código é bastante legível. Uma solução C ++ 11 pareceria muito mais bonita, pois podemos usar lambdas

Versão C ++ 11 - sem necessidade de lambdas, mas o auto e o range baseados em tornam as coisas muito limpas (pense bem, você pode fazer muito semelhante ao C ++ 98 regular)

#include<iostream>
#include<iterator>
#include<map>
#include<set>
using namespace std;int main(){istream_iterator<char> b(cin),e;map<char,int> c;set<pair<int,char>> d;for(char i='A';i<='Z';++i){--c[i];}for(auto i=b;i!=e;++i){c[toupper(*i)]--;}for(auto p:c){d.insert(make_pair(p.second,p.first));}for(auto p:d){cout<<p.second;}}

Versão expandida:

#include <iostream>
#include <iterator>
#include <map>
#include <set>
using namespace std;
int main()
{
    istream_iterator<char> b(cin), e;
    map<char, int> c;
    set<pair<int, char>> d;
    for(char i = 'A'; i <= 'Z'; ++i) {--c[i];}
    for(auto i = b; i != e; ++i) {c[toupper(*i)]--;}
    for(auto p : c) { d.insert(make_pair(p.second, p.first)); }
    for(auto p : d) { cout << p.second; }
}

Próxima iteração (por que ler do stdin quando temos argv):

#include <set>
#include <iostream>
int c[256];int main(int n, char **s){std::set<std::pair<int,char>> d;while(*s[1]){c[toupper(*s[1]++)]--;}for(n=65;n<92;++n){d.insert(std::make_pair(--c[n],n));}for(auto p:d){std::cout<<p.second;}}

Versão expandida:

#include <set>
#include <iostream>
int c[256];
int main(int n, char **s)
{
    std::set<std::pair<int, char>> d;
    while (*s[1])
    {
        c[toupper(*s[1]++)]--;
    }
    for (n = 65; n < 92; n++)
    {
        d.insert(std::make_pair(--c[n], n));
    }
    for (auto p : d)
    {
        std::cout << p.second;
    }
}

3

Gelatina , 9 bytes (não concorrente)

ØAŒuċ¥@ÞU

Explicação

ØAŒuċ¥@ÞU  Main Link
       Þ   Sort
ØA         The uppercase alphabet by
  Œuċ¥@    number of occurrences in the input:
  Œu       Uppercase
    ċ      Count occurrences
     ¥     Grammar: Last two links as a dyad
      @    Swap arguments
        U  Reverse (because sort sorts up)

É lido como "classificar o alfabeto maiúsculo pelo número de ocorrências na entrada maiúscula, invertida", que é uma tradução literal do desafio: P

Experimente online!

Esse desafio foi vinculado ao Jelly HyperTraining, onde resolvemos o desafio. Postei isso porque fui o primeiro a atingir 10 bytes.

-1 byte graças a Erik the Outgolfer (professor JHT)


9 bytes:ØAŒuċ¥@ÞU
Erik the Outgolfer

@EriktheOutgolfer Oh legal, obrigado!
HyperNeutrino

2

C ++ 377

Implementa qsort usando contagens de letras na matriz n para classificar o alfabeto na matriz A. Execute via linha de comando: golf.exe < in.txt

int n[26],c,k,N;
char A[26];
int C(const void*a,const void*b)
{
int i=(int)(*(char*)a -'A');
int j=(int)(*(char*)b -'A');
return n[j]-n[i];
}
int main()
{
for(;k<26;k++)
{
A[k]=k+'A';
}
N=sizeof(A);
c=getchar();
while(c>0)
{
c=toupper(c);
c=c-'A';
if(c>=0&&c<26)n[c]++;
c=getchar();
}
qsort(A,N,1,C);
for(k=0;k<N;k++)
{
putchar(A[k]);
}
return 0;
}

2

C, 117 (119) bytes

x[256];m=1;char c;main(){while(c=getchar()+1)++x[c-1&95];for(;m=x[++c]<x[m]?m:c;x[m<65|m>90||c?m*!c:putchar(m)]=-1);}
  • Algumas entradas que contêm códigos ASCII> = 128 aumentam incorretamente as frequências das letras. Para corrigir isso, substitua a constante 95por 223, a um custo de 1 byte extra.
  • Isso terminará cedo nas entradas que contêm o caractere com código ASCII 255. Para corrigir isso ao custo de 1 byte extra, altere char c;para just c;e ++cpara c=c+1%255.

2

PowerShell - 139 caracteres

Primeiro, não sou especialista em PowerShell. Tenho certeza que existem mais curtos que isso. Mas estava feliz com isso e decidiu compartilhar.

$a = Read-host
$b = ($a.ToUpper() -replace '[^A-Z]','').ToCharArray() + (65..90|%{[char[]]$_})|Group|sort Count -desc|%{$_.Name}
-join $b

Como funciona:

$a = Read-host            # read from stdin and save into a string var $a
$a.ToUpper()              # Convert the string to UPPERCASE
-replace'[^A-Z]',''       # Remove all non A-Z characters from the str
(...).ToCharArray()       # Convert the inner object (string) to a Char Array
+  (65..90|%{[char[]]$_}) # Create another char array with A-Z chars expanded, 
                          #  and append it to the previous one.
|Group                    # Group the char array by value for each element, 
                          #  consolidates them and count each char occurrence. Example:
                          #  Count | Name
                          #  ----- | -----
                          #      4 | B
                          #      1 | F
                          #      2 | C 
                          #     .. | ..
                          # 
|sort Count -desc         # Sorts the previous hash-table by the 'Count' column 
                          #   in desc ordering
|%{$_.Name}               # Grab only the 'Name' column from the previous sorted hash-table. 
                          # The retuslt obj will be a simple char array again, 
                          #   with the letters in the desired order
$b = (...)                # Saves the resulting char array into a new variable $b
-join $b                  # join the resulting char array elements into a single 
                          #   string, and print it to stdout. 

2

Ceilão , 98 bytes

String f(String s)=>String(('A':26).sort(byDecreasing((Object c)=>s.uppercased.count(c.equals))));

2

APL, 26 20 caracteres

⎕a[⍒+/⎕a∘.=('\w'⎕r'\u0')⍞]

⎕a[⍒+/⎕a∘.=1(819⌶)⍞]

-6 graças a Adam.


1
('\w'⎕r'\u0')1(819⌶)
Adám
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.