Palabra con mayor repetición de letras

8

Recientemente hubo una pregunta sobre Stack Overflow en la que el OP estaba tratando de escribir una función para encontrar la palabra en una cadena que tiene las letras más repetidas. Por supuesto, no es difícil escribir uno en segundos, y escribí uno en Javascript lo más breve posible por diversión. Pero no soy un experto en golf de código, así que me pregunto cuánto más corto puede ser este simple programa.


Desafío

Escriba un programa o función que tome una cadena de palabras y devuelva o imprima la palabra con las letras individuales más repetidas.

Reglas:

  • Elija la palabra con el mayor número de letras simples repetidas (vea los ejemplos a continuación)

  • Si ninguna palabra tiene letras repetidas, devuelve -1.

  • Si dos palabras tienen el mismo número máximo de letras repetidas, elija la más cercana al comienzo de la cadena.

  • La presentación más corta en bytes gana.

Entrada

Tome como entrada una cadena que consta de una o más palabras delimitadas por espacios. La entrada puede ser de STDIN (o la alternativa más cercana), parámetros de línea de comando o argumentos de función.

Salida

Imprima el resultado en STDOUT para devolverlo.

Ejemplos

Considera la cuerda aaabbb cccc. Este contiene dos palabras: aaabbby cccc. La palabra aaabbbtiene 3 ay 3 b, y cccctiene 4 c. Entonces, el número máximo de letras repetidas aaabbbes 3 y el máximo cccces 4. Queremos elegir la palabra con el número máximo de letras simples repetidas, por lo que la salida para aaabbb ccccdebería ser cccc.

Otros casos de prueba:

Today, is the greatest day ever!  --> greatest
This is a great day               --> -1
aaabbb cccc                       --> cccc
Derek 朕 會 功夫
fuente
¿Qué pasa si más de una palabra tiene el mismo número de letras repetidas? ¿Imprimimos alguno o todos?
Maltysen
@Maltysen Mira el primer ejemplo - miraever
isaacg
@isaacg pero great tiene dos repeticiones, tye.
Maltysen
2
No estoy seguro de qué se entiende por el número de letras repetidas. Supongo que aabbtiene 2 letras repetidas. Se aaaabbconsideraría que tiene 4 letras repetidas (2da, 3ra, 4ta a, 2da b) o 2 letras repetidas ( ay b).
fiesta del
1
Tenga en cuenta que la pregunta original es de Coderbyte. Busqué información de derechos de autor en su sitio web (ya que esta es una reproducción del Letter Count I) pero no pude encontrar nada.
Alex A.

Respuestas:

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

Se actualizará cuando pueda truncarlo un poco

Cómo compilar: gcc -w cg.c

Cómo ejecutar: ./a.out word1 word2 aass ddaaa ssdddd

Salida: ssdddd

Sin salida / sin coincidencia: -1

En primer lugar, hice trampa un poco, al tomar las palabras como argumentos del programa, pero lograr que GCC analizara las palabras y me diera un recuento de palabras gratis fue una recompensa demasiado grande para dejarla pasar.

¿Como funciona?

Tenemos 3 bucles anidados. El primer incremento a través de cada palabra, los siguientes dos están imitando un tipo de burbuja para comparar valores. La primera letra nunca se compara consigo misma, y ​​cada letra subsiguiente se compara con cada letra anterior. Cada vez que una palabra tiene más letras iguales que una palabra anterior, la palabra se almacena en x, y el recuento de cuántas letras también se almacena.

Abuso de CCG

Usamos delimitaciones globales implícitas globales para nuestros enteros. Permitimos que argv sea un int en lugar de un char (actualmente un char, este es un TODO). Hacemos uso de funciones predeterminadas como Put y Getchar. También utilizamos el operador de coma para sobrecargar nuestro operador trinario (condicional).

¿Quieres 2 bytes menos?

Reemplace "-1" con * z y nombre el archivo -1

Programa no ofuscado y no probado:

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;
}
Jake
fuente
1
Bienvenido a PPCG! Buen golf; si tienes tiempo, me encantaría ver una explicación de cómo funciona tu código.
Toby Speight
OP actualizado con una explicación
Jake
Sin abuso de GCC, solo un poco de estilo antiguo pero regular C
edc65
eso es un récord! felicidades
Abr001am
4

Pyth, 14 bytes

eoeS/LNN+czd_1

Demostración. Prueba de arnés.

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.
isaacg
fuente
Todavía no parece estar funcionando. Según el comentario de feersum, "aaaabb" debe tener 4 repeticiones y, por lo tanto, más que "el mejor". Pero pyth.herokuapp.com/… todavía da lo mejor.
Maltysen
Poner un lantes .-parece hacerlo.
Maltysen
@Maltysen Correcto, era tonto e intenté usar la clasificación de cadenas.
isaacg
Esto es corto y hermoso.
Derek 朕 會 功夫
@Derek 朕 會 功夫 ¡Gracias! Considera la posibilidad de votar.
isaacg
2

K, 35 bytes (falta el requisito -1, lo acabo de notar, pero es hora de dormir)

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

cómo funciona:

1 toma

1#

de las palabras indexadas por

w[

los índices para poner en orden ascendente

>

el maximo

|/

cuenta donde

#:&:

cadena = char

x=y

por cada char en palabra

'x

para cada palabra donde w(palabras) son

'w:

la cadena dividida por espacios

\:x

Obviamente sacrifiqué un poco de precisión por expresividad y legibilidad en la explicación en inglés. Espero que haya sido interesante.

protista
fuente
1
Creo que puede seguir el requisito agregando ,-1al final de la función.
kirbyfan64sos
Debería poder dejar los dos puntos #:&:ya que, por contexto, deberían analizarse como sus formas monádicas. También puede usar @para indexar en lugar de corchetes, y first ( *) en lugar de 1#.
JohnE
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

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

Cómo 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 (no probado)

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

Esto utiliza sortOndesde Data.Listv4.8.0.0, que no he instalado, por lo que no puedo probarlo.

nimi
fuente
2

CJam, 25 bytes

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

Pruébalo en línea

Explicación:

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.
Reto Koradi
fuente
2

Python 2, 97 77 Bytes

Solución bastante sencilla, solo asigna la entrada (entre comillas) a una tupla que contiene la palabra y el número de caracteres repetidos. Obtiene el máximo e imprime la palabra si la letra más repetida se repite; de ​​lo contrario, imprime -1.

Ahorré 20 (!) Bytes al reorganizar el orden de entrada para que no necesitara una clave para encontrar el máximo.

j=max((max(map(x.count,x)),x)for x in input().split())
print[-1,j[1]][j[0]>1]
Kade
fuente
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.

Ejemplo: a("Today, is the greatest day ever!",R).salidas R = "greatest" ..

Fatalizar
fuente
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 apto para el golf, toda la cosa -1 agregó unos 20 bytes.

Downgoat
fuente
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))

Esto lee de STDIN e imprime en STDOUT.

Ungolfed + explicación:

# 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)
Alex A.
fuente
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;}

Codificación sencilla. Nada especial aquí.

C # apesta para golf de código: - /

Stephan Schinkel
fuente
1

JavaScript ( ES7? ), 99

Utilizando la comprensión de matriz, eso se implementa en Firefox pero no se incluye más en EcmaScript 6.

Pruebe utilizando el fragmento a continuación (solo 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 y más compatible

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>

edc65
fuente
1

Pitón, 58

max('-1',*input().split(),key=lambda w:len(w)-len(set(w)))
La cripta
fuente
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;}

INTENTALO

¿COMO FUNCIONA ESTO?

  • la función es recursiva interna una dentro de otra función recursiva, la función interna recupera el comienzo de una cadena donde la primera función devuelve un carácter inclusivo.
  • El número máximo viene dado por los caracteres hash sobre una tabla ASCII.
Abr001am
fuente
1

Q (44 bytes)

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

sin golf

{
    words:" " vs "-1 ",x;
    counts:{max count each group x} each words;
    : words counts ? max counts;
}
scottstein37
fuente
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

`` `


res una función que toma una palabra y devuelve una tupla (n,w)donde nes el número de ocurrencia del carácter más frecuente en la palabra w. Por ejemplo x="norep", y="dnredundant", entoncesr x=(1,norep), r y=(3,ndredundant)

w es una función que toma una cadena que contiene varias palabras separadas por espacios y:

  1. Dividir la lista en el espacio. words p

  2. cada palabra crea una lista de (n,w)

  3. tomar la tupla que tiene el mayor n(contador de ocurrencia)

  4. Si tiene n igual a 1, simplemente devuelve la cadena -1, la palabra misma (almacenada en el segundo componente de la tupla) de lo contrario.

Por ejemplo, tome p="Today, is the greatest day ever!"

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

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

  3. (2, "mayor")

  4. 2! = 1 entonces greatestes la solución!

Davide Spataro
fuente
1

Pure Bash (sin comandos externos) 129 bytes

Esto es bastante largo, pero aún se compara favorablemente con algunas de las otras entradas más largas.

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

No estoy del todo contento con algunos de los elementos, tener que usar ese bucle for interno es molesto. ¿Alguna sugerencia?

Muzer
fuente