Palavra com maior repetição de letras


8

Recentemente, houve uma pergunta no Stack Overflow em que o OP estava tentando escrever uma função para encontrar a palavra em uma string com as letras mais repetidas. Obviamente, não é difícil escrever uma em segundos, e eu escrevi uma em Javascript o mais curta possível para me divertir. Mas eu não sou especialista em golfe por código, então me pergunto quanto mais curto pode ser esse programa simples!


Desafio

Escreva um programa ou função que capte uma sequência de palavras e retorne ou imprima a palavra com as letras únicas mais repetidas.

Regras:

  • Escolha a palavra com o maior número de letras únicas repetidas (veja exemplos abaixo)

  • Se nenhuma palavra tiver letras repetidas, retorne -1.

  • Se duas palavras tiverem o mesmo número máximo de letras repetidas, escolha a mais próxima do início da sequência.

  • O menor envio em bytes vence.

Entrada

Tome como entrada uma sequência que consiste em uma ou mais palavras delimitadas por espaço. A entrada pode ser de STDIN (ou alternativa mais próxima), parâmetros de linha de comando ou argumentos de função.

Resultado

Imprima a saída em STDOUT para devolvê-la.

Exemplos

Considere a string aaabbb cccc. Isso contém duas palavras: aaabbbe cccc. A palavra aaabbbtem 3 a'e 3 b' e cccctem 4 c'. Portanto, o número máximo de letras repetidas em aaabbbé 3 e o máximo em ccccé 4. Queremos escolher a palavra com o número máximo de letras únicas repetidas, portanto a saída para aaabbb ccccdeve ser cccc.

Outros casos de teste:

Today, is the greatest day ever!  --> greatest
This is a great day               --> -1
aaabbb cccc                       --> cccc

E se mais de uma palavra tiver o mesmo número de letras repetidas? Nós imprimimos algum ou todos?
Maltysen

@Maltysen Veja o primeiro exemplo - seeever
isaacg

@isaacg mas o maior tem dois repetidos, te.
Maltysen

2
Não sei ao certo o que significa o número de letras repetidas. Suponho que aabbtem 2 letras repetidas. Seria aaaabbconsiderado como tendo 4 letras repetidas (2ª, 3ª, 4ª a, 2ª b) ou 2 letras repetidas ( ae b).
feersum

1
Observe que a pergunta original é de Coderbyte. Procurei no site deles informações sobre direitos autorais (uma vez que esta é uma reprodução do Conde I da letra), mas não consegui encontrar nada.
Alex A.

Respostas:


7

C - GCC - 159 145 135 bytes

x=0,w=0,i,j,c;main(int _,char**z){while(--_)for(j=i=0;_[z][i];j=++i,x=c>x?w=_,c:x)for(c=0;j--;)c+=z[_][i]==z[_][j];puts(x?z[w]:"-1");}

Será atualizado quando eu puder truncá-lo um pouco

Como compilar: gcc -w cg.c

Como executar: ./a.out word1 word2 aass ddaaa ssdddd

Saída: ssdddd

Sem saída / sem correspondência: -1

Primeiro, trapacei um pouco, incorporando as palavras como argumentos do programa, mas fazer com que o GCC analise as palavras e me forneça uma contagem de palavras de graça foi recompensa demais para deixar passar.

Como funciona?

Temos 3 loops aninhados. O primeiro incrementando cada palavra, as próximas duas imitam uma classificação de bolha para comparar valores. A primeira letra nunca é comparada consigo mesma e cada letra subsequente é comparada a cada letra anterior. Sempre que uma palavra tem mais mesmas letras que uma palavra anterior, a palavra é armazenada em x, e a contagem de quantas mesmas letras também é armazenada.

Abuso do GCC

Usamos descargas automáticas globais implícitas para nossos números inteiros. Permitimos que argv seja um int em vez de um caractere (atualmente um caractere, este é um TODO). Utilizamos funções padrão, como puts e getchar. Também usamos o operador de vírgula para sobrecarregar nosso operador trinário (condicional).

Quer 2 bytes a menos?

Substitua "-1" por * z e nomeie o arquivo -1

Programa não ofuscado e não testado:

int main(int argc, char * argv[])
{
    int word = 0           // Current most repeat letters word
    int count = 0;        // Current most repeat letters
    int i, j, increment; // Counter variables

    while(--argc != 0) // While we have words from program parameters
    {
        for(j = i = 0; argv[argc][i] != '\0'; j = ++i) // Iterate through each letter until end of word
        {
            for(increment = 0; j > 0; j--) // Iterative backwards through each letter
            {
                if(argv[argc][i] == argv[argc][j])
                {
                    increment++;
                }
            }
            if(increment > count) // New greatest lettered word
            {
                word = argc;
                count = increment;
            }
        }
    }

    if(word == 0)
    {
        puts("-1");
    }
    else
    {
        puts(argv[word]);
    }

    return 0;
}

1
Bem-vindo ao PPCG! Bom golfe; se você tiver tempo, adoraria ver uma explicação de como seu código funciona.
precisa

OP atualizado com uma explicação
Jake

Nenhum abuso GCC, apenas algum estilo antigo, mas C regulares
edc65

isso é um recorde! parabéns
Abr001am

4

Pitão, 14 bytes

eoeS/LNN+czd_1

Demonstração. Equipamento de teste.

eoeS/LNN+czd_1
                  Implicit: z = input(), d = ' '
         czd      chop z on delimeter d.
        +   _1    Add an -1 to the end of the list.
 o                Order the list by
  eS              the maximum of
    /LN           the occurence count in the word
       N          of letters in the word.
                  (If we are mapping over -1, this will give -1/-1 = 1)
                  Since Python's sort is stable, this will leave -1 at the end if
                  all words have maximum repetition count 1.
e                 Take the final element of the resulting list and print it.

Ainda não parece estar funcionando. Conforme comentário do feersum, "aaaabb" deve ter 4 repetições e, portanto, mais que "maior". Mas pyth.herokuapp.com/… ainda dá o melhor.
Maltysen

Colocar um lantes .-parece fazê-lo.
Maltysen

@ Maltysen Certo, eu era bobo e tentei usar a classificação por cordas.
Isaacg

Isso é curto e bonito.
Derek朕會功夫

@Derek 朕 會 功夫 Obrigado! Considere votar.
Isaacg

2

K, 35 bytes (faltando -1 requisito, acabei de notar, mas é hora de dormir)

{1#w[>{|/{#:&:x=y}[x]'x}'w:" "\:x]}

como funciona:

1 tomada

1#

das palavras indexadas por

w[

os índices para colocar em ordem crescente

>

o máximo

|/

conte onde

#:&:

string = char

x=y

para cada caractere em palavra

'x

para cada palavra em que w(palavras) são

'w:

a sequência dividida por espaços

\:x

Obviamente, sacrifiquei um pouco de precisão por expressividade e legibilidade na explicação em inglês. Espero que tenha sido interessante.


1
Eu acho que você pode seguir o requisito adicionando ,-1ao final da função.
kirbyfan64sos

Você deve deixar de fora os dois pontos, #:&:pois, a partir do contexto, eles devem analisar como suas formas monádicas. Você também pode usar @para indexar em vez de colchetes e primeiro ( *) em vez de 1#.
precisa saber é

2

Haskell, 100 bytes

import Data.List
f=g.last.sort.map((,)=<<last.sort.map length.group.sort).words
g(1,_)="-1"
g(_,w)=w

Exemplo de uso: f "Today, is the greatest day ever!"->"greatest"

Como funciona:

                                                words  -- split input at spaces into list of words
          map(                                 )       -- for each word
              (,)=<<                                   -- build a pair, where the second element is the word itself
                                                       -- and the first element is made by
                                           sort        -- sort the letters
                                      group            -- group equal letters
                            map length                 -- take length of each group
                        sort                           -- sort the lengths
                    last                               -- take the last
                                                       -- now we have a list of (l,w) pairs where l is how often the most frequent letter occurs for word w
     sort                                              -- sort the list
 last                                                  -- take last element
g                                                      -- call g which checks the "-1" case 

Haskell, 79 77 bytes (não testado)

import Data.List
last.sortOn(last.sort.map length.group.sort).words.(++" -1")

Isso usa sortOnda Data.Listv4.8.0.0, que eu não tenho instalado, então não posso testá-lo.


2

CJam, 25 bytes

lS/{_$e`$W=0=(\}%2/$W=~W?

Experimente online

Explicação:

lS/   Get input and split at spaces.
{     Start of loop over all words.
  _     Copy, need to keep original word.
  $     Sort letters.
  e`    RLE.
  $     Sort RLE result. Sort is increasing by count.
  W=    Get last count/letter pair, which corresponds to largest count.
  0=    Extract count from pair.
  (     Decrement count, so that it has a falsy value when the count is 1.
  \     Swap count and word, so that we can sort the pairs by count.
}%    End of loop over words.
2/    Split list into pairs, which are the count/word pairs.
$     Sort the pairs.
W=    Get last one, which is the largest count.
~     Unwrap the pair.
W?    Output word if count is truthy, -1 otherwise.

2

Python 2, 97 77 bytes

Solução bastante direta, apenas mapeia a entrada (entre aspas) para uma tupla contendo a palavra e o número de caracteres repetidos. Obtém o máximo e imprime a palavra se a letra mais repetida for repetida, caso contrário, ela imprime -1.

Salvei 20 (!) Bytes reorganizando a ordem de entrada para não precisar de uma chave para encontrar o valor máx.

j=max((max(map(x.count,x)),x)for x in input().split())
print[-1,j[1]][j[0]>1]

1

SWI-Prolog, 158 154 149 bytes

a(A,R):-split_string(A," ","",B),findall(X:Z,(member(Z,B),string_codes(Z,D),length(D,L),sort(D,E),length(E,M),X is M-L,X<0),S),sort(S,[_:R|_]);R= -1.

Exemplo: a("Today, is the greatest day ever!",R).saídas R = "greatest" ..


1

JavaScript, 86 111 108 bytes

s=>(l=(x=s.split` `,r=x.map(l=>(/(.)\1+/.exec(l)||[''])[0].length),x)[r.indexOf(k=Math.max(...r))],k<2?-1:l)

Definitivamente capaz de jogar golfe, a coisa toda -1 adicionou cerca de 20 bytes.


1

R, 107 bytes

w=scan(,"");l=sapply(w,function(x)max(table(strsplit(x,"")[[1]])));cat(ifelse(max(l)>1,w[which.max(l)],-1))

Ele lê STDIN e imprime em STDOUT.

Ungolfed + explicação:

# Read a string and split it into a vector on spaces
w <- scan(, "")

# Get the maximum number of letter repeats in each element of w
l <- sapply(w, function(x) max(table(strsplit(x, "")[[1]])))

# If the largest number in l is 1, print -1, otherwise get the word
cat(ifelse(max(l) > 1, w[which.max(l)], -1)

1

C # 166 bytes

string a(string i){var z=i.Split(' ');int g=1,c=0;var m="-1";foreach(var w in z)foreach(var l in w.Distinct()){c=w.Where(x=>x==l).Count();if(c>g){g=c;m=w;}}return m;}

Codificação simples. Nada de especial aqui.

C # é péssimo para código de golfe: - /


1

JavaScript ( ES7? ), 99

Usando compreensão de matriz, implementada no Firefox, mas não mais incluída no EcmaScript 6.

Teste usando o trecho de código abaixo (somente Firefox)

f=s=>s.split(' ').map(w=>[for(c of(l=[m=0],w))(n=l[c]=-~l[c])>m?m=n:0]&&m>x&&(x=m,v=w),x=1,v=-1)&&v

// TEST
out=x=>O.innerHTML+=x+'\n';

test=x=>out(x+' -> '+f(x))

;["aaabbb cccc","This is a great day","Today, is the greatest  day ever a!"]
.forEach(t=>test(t));
<pre id=O></pre>
Try:<input id=I><button onclick='test(I.value),I.value=""'>-></button>

Ungolfed E mais compatível

function f(s)
{
  v = -1;
  x = 1;
  s.split(' ')
  .forEach(function(w){
    l=[];
    m=0;
    w.split('').forEach(function(c){
      n=l[c]=-~l[c];
      if (n>m) m=n;
    })
    if (m>x) x=m,v=w;
  })
  return v;
}

// TEST
out=function(x) { O.innerHTML+=x+'\n' }

test=function(x) { out(x+' -> '+f(x)) }

;["aaabbb cccc","This is a great day","Today, is the greatest  day ever a!"]
.forEach(function(t) { test(t)} );
<pre id=O></pre>
Try:<input id=I><button onclick='test(I.value),I.value=""'>-></button>


1

Python, 58

max('-1',*input().split(),key=lambda w:len(w)-len(set(w)))

1

C (167)

double m,k,n=k=2,*O,V[256];char*f(char*c,char*s){return*c?((*O=!((n+=!(*c*=*c!=32))>1.1/modf(*(O=V+*c),&m))*m+1/n+1)>k)?f(c+!!(k=*O),c):f(c+1,s):s?!*s?s+1:f(c,s-1):0;}

TENTE

COMO É QUE ISSO FUNCIONA?

  • a função é recursiva interna, uma dentro de outra função recursiva, a função privilegiada recupera o início de uma sequência em que um caractere inclusivo é retornado pela primeira função.
  • o número máximo é dado por caracteres de hash sobre uma tabela ascii.

1

Q (44 bytes)

{w l?0|/l:{max(#:)'[(=)x]}'[w:" "vs"-1 ",x]}

destroçado

{
    words:" " vs "-1 ",x;
    counts:{max count each group x} each words;
    : words counts ? max counts;
}

1

Haskell 96 Bytes


r o=(last.sort.map length$(group.sort)o,o)
w p=n$maximum(map(r)(words p))
n (1,_)="-1"
n (_,w)=w

`` ``


ré uma função que pega uma palavra e retorna uma tupla (n,w)onde né o número de ocorrência do caractere mais ocorrente na palavra w. Por exemplo x="norep", y="dnredundant", deixe , entãor x=(1,norep), r y=(3,ndredundant)

w é uma função que utiliza uma sequência que contém várias palavras separadas por espaço e:

  1. Dividir a lista no espaço words p

  2. foreach palavra criar uma lista de (n,w)

  3. pegue a tupla que tem o maior n(contador de ocorrências)

  4. Se n for igual a 1, basta retornar a string -1, a própria palavra (armazenada no segundo componente da tupla), caso contrário.

Por exemplo, pegue p="Today, is the greatest day ever!"

  1. produz ["Today,","is","the","greatest","day","ever!"]

  2. [(1,"Today,"),(1,"is"),(1,"the"),(2,"greatest"),(1,"day"),(2,"ever!")]

  3. (2, "maior")

  4. 2! = 1, então greatesté a solução!


1

Pure Bash (sem comandos externos) 129 bytes

Isso é bastante longo, mas ainda se compara favoravelmente com algumas das outras entradas mais longas.

m=1
w=-1
for b;{
declare -A a
for((i=0;i<${#b};i++));{
c=${b:$i:1}
let a[$c]++
d=${a[$c]}
((d>m))&&w=$b&&m=$d
}
unset a
}
echo $w

Não estou totalmente satisfeito com algumas das constantes, ter que usar esse loop for interno é irritante. Alguma sugestão?

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.