Comer dulces en el orden correcto

36

Cuando se trata de comer dulces, me mantengo en estándares más altos que el típico laico. Existe un delicado equilibrio entre "mezclarlo" y "guardar lo mejor para el final".

En este desafío, se te dará una serie de personajes en los que cada personaje representa un dulce. Los diferentes caracteres (distinguen entre mayúsculas y minúsculas) representan diferentes tipos de dulces. Su programa debe determinar el orden correcto de consumo de dulces, de acuerdo con el siguiente procedimiento. Puede escribir un programa completo (STDIN / STDOUT) o una función con nombre para realizar esta tarea.

Digamos que mi alijo de dulces es oroybgrbbyrorypoprr. Primero, clasifico los dulces en montones del mismo tipo, con grandes cantidades en la parte superior, usando valores de caracteres ASCII más bajos como un desempate.

rrrrrr
oooo
bbb
yyy
pp
g

Luego, tomo cada fila de dulces y los esparto por igual a lo largo de un intervalo. Por ejemplo, si hay 3 dulces, uno se coloca 1/3 del camino, 2/3 del camino y al final.

.r.r.r.r.r.r
..o..o..o..o
...b...b...b
...y...y...y
.....p.....p
...........g

A continuación, voy por cada columna para crear el pedido de caramelo final rorbyroprbyorrobypg.

Entrada

Una cadena que contiene el alijo de dulces. La entrada para el ejemplo anterior podría haber sido:

oroybgrbbyrorypoprr

Salida

Una cadena que contiene el dulce se reorganizó en el orden correcto de consumo.

rorbyroprbyorrobypg

Tanteo

Este es el código de golf. La respuesta más corta en bytes gana. Aplican reglas estándar de código de golf.

PhiNotPi
fuente
¿Simplemente agrega un espacio más grande si los números de dulces son desiguales? Digamos, en este caso, si tuviera un caramelo más, ¿cómo se vería la cuadrícula?
Vajura el
38
Finalmente alguien que SABE comer caramelos.
Michael M.
12
Entonces ... básicamente un caramelo vacilante.
COTO
99
Esto realmente se acerca mucho a cómo como mi dulce. :)
Emil
3
¿Cuán codicioso puede ser una persona? ¿Hay un límite en la cantidad de dulces que se comen?
Alchymist

Respuestas:

12

CJam, 78 68 61 45 42 39 31 30 bytes

l$:L{L\/,~}${:DM+:MD/,LD/,d/}$

Toma la cadena de entrada a través de STDIN

Inspirado en el enfoque recursivo, pero un poco diferente. No hay necesidad de transposición o rectángulo en absoluto!

Cómo funciona:

l$:L                              "Sort the input line and store it in L";
    {     }$                      "Sort the string based on this code block output";
     L\/,~                        "Sort based on number of occurrences of each";
                                  "character in the full string";
            {               }$    "Sort the sorted string again";
             :DM+:M               "Store each character in D, add to M and update M";
                   D/,            "Count occurrences of D in M";
                      LD/,        "Count occurrences of D in L";
                          d/      "Sort string based on the ratio of two occurrences";

(Es triste que CJam ya no pueda completarse con Pyth debido a la necesidad de tanta hinchazón como sintaxis)

Pruébalo aquí

Optimizador
fuente
44
No creo que necesites el LCM; cualquier múltiplo debería funcionar. Esto debería permitirle reemplazar {_@_@{_@\%}h;/*}con :.
Dennis
<facepalm> no pensó en eso.
Optimizador
¡Felicitaciones por reducir a la mitad tu longitud!
isaacg
Siento sarcasmo en eso: D
Optimizer
11

Pyth , 25

shCoc/NhN/zhNm>o_/zZSzdUz

Utiliza un algoritmo completamente nuevo, inspirado en esta respuesta .

(implicit)          z = input()
(implicit)          print
s                   combine list of strings into one string
 h                  first list in
  C                 matrix transpose of (e.g. first characters in first list, etc.)
   o                order_by(lambda N:
    c                        float_div(
     /NhN                              N.count(N[0]),
     /zhN                              z.count(N[0])),
    m                        map(lambda d:
     >                           slice_head(
      o                                     order_by(lambda Z:
       _/zZ                                          -1*z.count(Z),
       Sz                                            sorted(z)),
      d                                     d),
     Uz                          range(len(z))

Paso a paso:

  1. Primero, clasificamos los caracteres por su comunidad, lazos rotos alfabéticamente. Esto es o_/zZSz. oes lo mismo que Python sorted(<stuff>,key=<stuff>), con una expresión lambda para la clave, excepto que la mantiene como una cadena.

  2. Luego generamos una lista de los prefijos de esa cadena, a partir de la longitud len(z) a longitud 1. >es equivalente a la de Python <stuff>[<int>:].

  3. Luego, reordenamos esta lista de cadenas de prefijos por la ubicación fraccional, siendo 0 el borde izquierdo y 1 el derecho, del primer carácter del prefijo en el diseño rectangular visto en la pregunta. /NhNcuenta cuántas veces aparece el primer carácter en el prefijo en el prefijo, mientras/zhN da el número de apariciones del primer carácter en el prefijo en la cadena como un agujero. Esto asigna a cada prefijo dirigido por cada personaje en un grupo una fracción diferente, desde1/k la aparición más a la derecha de ese personaje hasta k/kla más a la izquierda. Reordenar la lista de prefijos por este número proporciona la posición adecuada en el diseño. Los empates se rompen usando el pedido anterior, que primero se hizo por conteo y luego por orden alfabético, según lo deseado.

  4. Finalmente, necesitamos extraer el primer carácter de cada cadena de prefijo, combinarlos en una sola cadena e imprimirlos. Extraer los primeros caracteres es hC. Crealiza una transposición matricial en la lista, zip(*x)en realidad en Python 3.h extrae la primera fila de la matriz resultante. Esta es en realidad la única fila, porque la presencia del prefijo de 1 carácter evita que se formen otras filas completas. ssuma los caracteres de esta tupla en una sola cadena. La impresión es implícita.

Prueba:

$ pyth -c 'shCoc/NhN/zhNm>o_/zZSzdUz' <<< 'oroybgrbbyrorypoprr'
rorbyroprbyorrobypg

Piezas incrementales del programa sobre oroybgrbbyrorypoprr:

Sub-Piece                  Output

Sz                         bbbgoooopprrrrrryyy
o_/zNSz                    rrrrrroooobbbyyyppg      (uses N because o uses N on first use.)
m>o_/zNSzdUz               ['rrrrrroooobbbyyyppg', 'rrrrroooobbbyyyppg', 'rrrroooobbbyyyppg', 'rrroooobbbyyyppg', 'rroooobbbyyyppg', 'roooobbbyyyppg', 'oooobbbyyyppg', 'ooobbbyyyppg', 'oobbbyyyppg', 'obbbyyyppg', 'bbbyyyppg', 'bbyyyppg', 'byyyppg', 'yyyppg', 'yyppg', 'yppg', 'ppg', 'pg', 'g']
oc/NhN/zhNm>o_/zZSzdUz     ['roooobbbyyyppg', 'obbbyyyppg', 'rroooobbbyyyppg', 'byyyppg', 'yppg', 'rrroooobbbyyyppg', 'oobbbyyyppg', 'pg', 'rrrroooobbbyyyppg', 'bbyyyppg', 'yyppg', 'ooobbbyyyppg', 'rrrrroooobbbyyyppg', 'rrrrrroooobbbyyyppg', 'oooobbbyyyppg', 'bbbyyyppg', 'yyyppg', 'ppg', 'g']
Coc/NhN/zhNm>o_/zZSzdUz    [('r', 'o', 'r', 'b', 'y', 'r', 'o', 'p', 'r', 'b', 'y', 'o', 'r', 'r', 'o', 'b', 'y', 'p', 'g')]
shCoc/NhN/zhNm>o_/zZSzdUz  rorbyroprbyorrobypg

Vieja respuesta:

Pyth , 34

ssCm*+t*u*G/zHS{-zd1]kd/zdo_/zNS{z

Este programa funciona calculando cuántas veces replicar una determinada sublista. La sublista se ve así ['', '', '', '', ... , 'r']. La longitud total de esta sublista es el producto del número de ocurrencias de todos los otros dulces, que es u*G/zHS{-zd1. La sublista completa se construye replicando la lista de la cadena vacía ]k, que muchas veces, luego eliminando y elemento cont y agregando el nombre del caramelo al final con +d.

Luego, esta sublista se replica tantas veces como se encuentra ese dulce en la entrada, /zd , asegurando que la lista de cada dulce sea de igual longitud.

Ahora, con esta función asignada a todos los dulces únicos en el orden ordenado apropiado ( o_/zNS{z), tenemos un rectángulo similar al de la pregunta, pero con cadenas vacías en lugar de puntos. Hacer una transposición matricial ( C) seguida de dos sumaciones ( ss) da la cadena final.

Verificación:

$ pyth programs/candy.pyth <<< 'oroybgrbbyrorypoprr'
rorbyroprbyorrobypg
isaacg
fuente
44
¡Parece que Pyth admite el cifrado en la sintaxis del lenguaje mismo!
Optimizador
¿Cifrado de optimizador? ¿De qué estás hablando?
isaacg
¡Agradable! Probablemente nunca hubiera pensado cambiar el bucle for en un mapa. Mucho más limpio.
FryAmTheEggman
Mira el código fuente. Parece un mensaje encriptado.
Optimizador
2
¿Puedes dar un ejemplo paso a paso del último algoritmo? Bastante por favor :)
Optimizador
6

Perl 5 - 62

61 código + 1 bandera.

#!perl -n
print map/(.$)/,sort map/(.$)/*$_/$$1.~$_.$1,map++$$_.$_,/./g

Primero divide la entrada en una matriz de caracteres: /./g .

Agregue índice de ocurrencia a cada letra dejando los recuentos en variables $a... $zcon map++$$_.$_. Ahora la matriz es:

1o
1r
2o
1y
1b
1g
2r
2b
3b
2y
3r
3o
4r
3y
1p
4o
2p
5r
6r

Luego conviértalo a una clave de clasificación que concatene: relación $_/$$1, recuento de desempate ~$_y disyuntor de valor ASCII $_. Esto resultará en (aquí con espacios adicionales para mayor claridad).

0.25 18446744073709551614 o
0.166666666666667 18446744073709551614 r
0.5 18446744073709551613 o
0.333333333333333 18446744073709551614 y
0.333333333333333 18446744073709551614 b
1 18446744073709551614 g
0.333333333333333 18446744073709551613 r
0.666666666666667 18446744073709551613 b
1 18446744073709551612 b
0.666666666666667 18446744073709551613 y
0.5 18446744073709551612 r
0.75 18446744073709551612 o
0.666666666666667 18446744073709551611 r
1 18446744073709551612 y
0.5 18446744073709551614 p
1 18446744073709551611 o
1 18446744073709551613 p
0.833333333333333 18446744073709551610 r
1 18446744073709551609 r

Esto se puede ordenar por orden lexicográfico (predeterminado). Al final, extraiga el último carácter e imprima:print map/(.$)/

nutki
fuente
5

Python 3.x - 124 bytes

C=input()
print("".join(s[1]for s in sorted(enumerate(C),key=lambda
t:((C[:t[0]].count(t[1])+1+1e-10)/C.count(t[1]),t[1]))))
recursivo
fuente
¡Este es un algoritmo mucho más genial que el método del rectángulo!
isaacg
4

Mathematica, 123 119 118 bytes

f=FromCharacterCode[s=SortBy;#&@@@s[Join@@(s[Tally@ToCharacterCode@#,-Last@#&]/.{x_,n_}:>({x,#/n}&~Array~n)),{Last}]]&

Define una función con nombre f. Sin golf:

f = FromCharacterCode[
   s = SortBy;
   # & @@@ s[
     Join @@ (
       s[
         Tally@ToCharacterCode@#,
         -Last@# &
         ] /. {x_, n_} :> ({x, #/n} &~Array~n)
       ),
     {Last}
     ]
   ] &

El uso de tipos racionales incorporados parecía una buena idea para esto. Por supuesto, esto no está cerca de CJam. Básicamente, estoy representando la cuadrícula que se muestra en el desafío como una lista de pares. Lo primero en el par es el código de caracteres, el segundo es su posición como una fracción menor o igual a 1 (la columna final es 1). Después de asegurarme de que los caracteres individuales ya están en el orden correcto, solo necesito ordenar esto de manera estable por dicha fracción para obtener el resultado deseado.

Martin Ender
fuente
3

Pyth 45 47 48 51

Esto también podría casi con toda seguridad ser más golfizado;)

Ko_/zNS{zFGK~Y]*+*t/u*GHm/zdK1/zG]k]G/zG)ssCY

Funciona construyendo una lista de listas, donde cada lista interna es una fila de cadenas vacías y el nombre del dulce. Esta lista se transpone y luego se unen las listas internas seguidas de estas listas.

¡Gracias @isaacg por recordarme sobre la suma!

FryAmTheEggman
fuente
2
sen una lista de cadenas funciona como j"".
isaacg
3

APL: 38

v⌷⍨⊂⍋⌽(n/-n),⍪∊+\¨n⍴¨÷n←{≢⍵}⌸v←{⍵[⍋⍵]}

Explicación:

v←{⍵[⍋⍵]}    orders input string
n←{≢⍵}⌸v     counts how many times each element appears in v
∊+\¨n⍴¨÷n     makes incremental sums in each letter "group" 
⍋⌽(n/-n),⍪   appends number of elements in letter group and orders the obtained matrix
v⌷⍨⊂         orders vector v with computed indices

Se puede probar en tryapl.org

Moris Zucca
fuente
2

R - 166 caracteres

library("plyr");s=function(a){l=table(strsplit(a,s="")[[1]]);l=ldply(l[order(-l,names(l))],function(n)data.frame(seq_len(n)/n));paste(l[order(l[[2]]),1],collapse="")}

versión sin golf

library("plyr")
s <- function(a) {
    tbl <- table(strsplit(a, split = "")[[1]])
    tbl <- tbl[order(-tbl, names(tbl))]
    tbl <- ldply(tbl, function(n) {data.frame(seq_len(n)/n)})
    paste(tbl[order(tbl[[2]]),1], collapse = "")
}

Explicación:

  • Dividir en caracteres individuales
  • Tabula el número de cada personaje
  • Ordenar la tabla en la más frecuente y luego por orden léxico
  • Indice las posiciones para la selección en 1 / n, 2 / n, 3 / n, ... n-1 / n, 1 donde n es el número de dulces
  • Ordene los nombres de dulces por índice ( orderes estable en la clasificación, por lo que mantendrá el orden de nombres más frecuente / léxico cuando haya un empate en el índice, particularmente importante con los últimos dulces)
  • Concatenar los nombres de dulces juntos para hacer la cadena de salida

La naturaleza matricial del problema me hizo pensar que R podría intentarlo, pero la mejor interpretación literal del algoritmo que pude hacer fue 211 caracteres:

l=function(a){l=table(strsplit(a,s="")[[1]]);l=l[order(-l,names(l))];o=Reduce(`*`,l);m=matrix("",nc=o,nr=length(l));for(r in seq_along(l)){x=l[r];for(c in seq_len(x)*o/x){m[r,c]<-names(x)}};paste(m,collapse="")}

sin golf:

l <- function(a) {
    tbl <- table(strsplit(a, split = "")[[1]])
    tbl <- tbl[order(-tbl, names(tbl))]
    o <- Reduce(`*`, tbl)
    m <- matrix("", ncol = o, nrow = length(tbl))
    for (r in seq_along(tbl)) {
        for (c in seq_len(tbl[r])*o/tbl[r]) {
            m[r,c] <- names(tbl[r])
        }
    }
    paste(m, collapse="")
}
Brian Diggs
fuente
2

Pyth, 29 bytes

Esta es una traducción directa de mi respuesta de CJam en Pyth

oc/|$Y.append(N)$YN/zNo_/zZSz

Pruébalo en línea aquí


Hay una historia bastante larga detrás de esta solución y @isaacg me ayudó mucho a comprender este nuevo lenguaje.

Idealmente, esta es la traducción exacta de palabra a palabra de mi código CJam ( 17 bytes ):

oc/~kNN/zNo_/zZSz

lo que significa:

o         order_by(lambda N:
 c                 div(
  /                    count(
   ~kN                       k+=N,                #Update k (initially ""), add N
   N                         N),                  #Count N in updated k
  /zN                  count(z, N)),
 o                 order_by(lambda Z:
  _                         neg(
   /zZ                          count(z, Z)),
  Sz                        sorted(z)))

Pero lamentablemente Python no devuelve nada en un += llamada, por lo que no era un código Python válido, por lo tanto, un código Pyth no válido también como en Pyth, un lambda solo puede ser una declaración de retorno.

Luego busqué en varios métodos y finalmente descubrí que Python list.appenddevuelve un Nonevalor, que puedo usar. Hacer que el código sea ( 19 bytes ):

oc/|aYNYN/zNo_/zZSz

lo que significa:

o         order_by(lambda N:
 c                 div(
  /                    count(
   |aYN                      (Y.append(N) or
    Y                         Y)                 #Update Y (initially []), append N
   N                         N),                 #Count N in updated Y
  /zN                  count(z, N)),
 o                 order_by(lambda Z:
  _                         neg(
   /zZ                          count(z, Z)),
  Sz                        sorted(z)))

Pero lamentablemente, el soporte de a(append) se eliminó de Pyth y la versión que sí lo tiene, no lo tiene o.

Actualización: ahora ase ha agregado soporte en Pyth, por lo que el código de 19 bytes anterior funcionará en el compilador en línea. Pero dado que esta es una nueva característica que se agregó después del OP, no la pongo como mi puntaje y dejo que el código de 29 bytes sea mi solución.

Por lo tanto, tuve que confiar en Python sin procesar en ese caso, haciendo que el código fuera

o         order_by(lambda N:
 c                 div(
  /                    count(
   |$Y.append(N)$            (Y.append(N) or
    Y                         Y)                 #Update Y (initially []), append N
   N                         N),                 #Count N in updated Y
  /zN                  count(z, N)),
 o                 order_by(lambda Z:
  _                         neg(
   /zZ                          count(z, Z)),
  Sz                        sorted(z)))
Optimizador
fuente