Hacer un patrón alternativo

8

Problema

Te dan una secuencia de bolas de colores (rojo Ry verde G). Una de esas posibles secuencias es:

RGGGRRGGRGRRRGGGRGRRRG

En el menor número de movimientos posible, debe hacerlo de modo que cada bola tenga un color diferente al de sus vecinos (es decir, la secuencia se alterna).

RGRGRGRGRGRGRGRGRGRGRG

Debe escribir un programa que pueda convertir una secuencia desordenada (en este caso, una cadena) con números iguales de "R" y "G" en una secuencia donde los elementos se alternan. A continuación se muestra una sesión de ejemplo, para un algoritmo ingenuo ( <se ingresa al programa, >se emite. No es necesario incluir los puntos en la entrada o salida).

< RGGGRRGGRGRRRGGGRGRRRG
> RGGRGRGGRGRRRGGGRGRRRG
> RGRGGRGGRGRRRGGGRGRRRG
> RGRGRGGGRGRRRGGGRGRRRG
> RGRGRGGRGGRRRGGGRGRRRG
> RGRGRGGRGRGRRGGGRGRRRG
> RGRGRGGRGRGRGRGRGGRRRG
> RGRGRGGRGRGRGRGRGRGRRG
> RGRGRGGRGRGRGRGRGRGRGR
> RGRGRGRGGRGRGRGRGRGRGR
> RGRGRGRGRGGRGRGRGRGRGR
> RGRGRGRGRGRGGRGRGRGRGR
> RGRGRGRGRGRGRGGRGRGRGR
> RGRGRGRGRGRGRGRGGRGRGR
> RGRGRGRGRGRGRGRGRGGRGR
> RGRGRGRGRGRGRGRGRGRGGR
> RGRGRGRGRGRGRGRGRGRGRG (15 moves)

Otra posibilidad es generar "5,7", por ejemplo, para indicar el intercambio de las posiciones 5 y 7.

Usted puede colocar ya sea rojo o verde en primer lugar, y usted no tiene que ser coherente. Cada secuencia tendrá la misma longitud que cualquier otra secuencia.

Solo puede intercambiar dos letras en cada movimiento (no es necesario que sean adyacentes).

Criterios ganadores

El programa debe mostrar cada paso del proceso de clasificación. El programa que realiza la menor cantidad de movimientos totales para todas las cadenas a continuación, gana. Si hay un empate, el código más corto ganará.

Cadenas de entrada

Las siguientes cadenas se utilizarán para probar los programas:

GGGGGGGGGGRRRRRRRRRR
GGRRGGRRGGRRGGRRGGRR
RRGGGGRRRRGGGGRRRRGG
GRRGRGGGGRRRGGGGRRRR
GRGGGRRRRGGGRGRRGGRR
RGRGRGRGRGRGRGRGRGRG

La última secuencia debería resultar en cero movimientos.

Thomas O
fuente
¿No debería "Solo puedes intercambiar dos pares en cada movimiento" como "Solo puedes intercambiar dos letras en cada movimiento"?
DavidC
@dude muy bien, lo corregiré.
Thomas O
¿Algún requisito de que una letra en particular comience la secuencia ordenada?
dmckee --- ex-gatito moderador
@dmckee De la pregunta: "Puede posicionar primero Rojo o Verde, y no tiene que ser coherente".
Thomas O
2
Buen problema para trabajar. Le sugiero que pida a la gente que publique varios ejemplos de sus entradas y salidas. De esta manera, aquellos que no programan en el idioma elegido pueden hacer una evaluación sobre la idoneidad de las salidas para las entradas respectivas.
DavidC

Respuestas:

5

Python, 140 122 119 115

r=raw_input()
f=lambda x:[i for i in range(x,len(r),2)if x-(r[i]!=max('RG',key=r[::2].count))]
print zip(f(0),f(1))
grc
fuente
1
Técnicamente no necesitas la asignación de s. Te ahorraría un par de personajes más.
kojiro
Sí, de nada. Tenía que hacer algo inteligente después de que derrotaras lo que estaba trabajando.
kojiro
3

APL 46

((2|y)/y←(i≠↑i)/n),[.1](~2|y)/y←(i=↑i)/n←⍳⍴i←⍞

Ejecutar los casos de prueba dados produce:

GGGGGGGGGGRRRRRRRRRR
11 13 15 17 19
 2  4  6  8 10

GGRRGGRRGGRRGGRRGGRR
3 7 11 15 19
2 6 10 14 18

RRGGGGRRRRGGGGRRRRGG
3 5 11 13 19
2 8 10 16 18

GRRGRGGGGRRRGGGGRRRR
3 5 11 17 19
4 6  8 14 16

GRGGGRRRRGGGRGRRGGRR
7  9 13 15 19
4 10 12 14 18

RGRGRGRGRGRGRGRGRGRG

La solución anterior utiliza el índice de origen 1 con los intercambios dados en las columnas de la matriz de resultados. Se pueden guardar dos caracteres si el vector de entrada i se inicializa con la cadena de entrada antes de la ejecución en lugar de ser ingresado en el momento de la ejecución.

Graham
fuente
3

GolfScript (47 caracteres)

:S;4,{S,,{.S=1&3*\1&2*^1$=},\;}%2/{zip}%{,}$0=`

Por ejemplo (usando un caso de prueba que es mucho más fácil verificar que sea correcto que cualquiera de los sugeridos, que tienen muchas respuestas correctas):

< RRGGRGRGRGRGRGRGRGRG
> [[1 2]]

La salida es una lista de pares indexados a cero para intercambiar.

Peter Taylor
fuente
Si [[1 2]] significa intercambiar letras en las posiciones 1 y 2, el resultado parecería ser idéntico a la entrada. Por favor aclarar
DavidC
44
@dude, ¿qué tipo de bicho raro comienza a contar en 1?
Peter Taylor
3
(Mi mano está levantada).
DavidC
2

Python, 213 caracteres

I=raw_input()
def M(S,T):
 S=list(S);m=[]
 while S!=list(T):z=zip(S,T);x=z.index(('R','G'));y=z.index(('G','R'));m+=[(x,y)];S[x],S[y]='GR'
 return m
N=len(I)/2
x=M(I,N*'RG')
y=M(I,N*'GR')
print[x,y][len(x)>len(y)]

Mdescubre los movimientos necesarios para convertir Sa T. Lo hace encontrando repetidamente un Ry un Gfuera de posición e intercambiándolos. Luego encontramos la secuencia de movimiento más corta para llegar a cualquiera RGRG...RGo GRGR...GR.

Debe encontrar una secuencia óptima de movimientos para cada entrada.

Keith Randall
fuente
2

Mathematica 238

Código

f[x_] := With[{g = "GRGRGRGRGRGRGRGRGRGR", c = Characters, p = Position},
y = c[x]; s = c[g]; {v = Equal @@@ ({s, y}\[Transpose]), 
w = Not /@ v}; {vv = Thread[{y, v}], ww = Thread[{y, w}]};
((Flatten /@ {p[#, {"R", False}], p[#, {"G", False}]}) &[If[Count[Equal @@@ 
({s, y}\[Transpose]), False] < 10, vv, ww]])\[Transpose]]

NB: \[Transpose]es un solo carácter, una "t" superíndice, en Mathematica ]

Ejemplos

f@"GGGGGGGGGGRRRRRRRRRR"
f@"GGRRGGRRGGRRGGRRGGRR"
f@"RRGGGGRRRRGGGGRRRRGG"
f@"GRRGRGGGGRRRGGGGRRRR"
f@"GRGGGRRRRGGGRGRRGGRR"
f@"RGRGRGRGRGRGRGRGRGRG"
f@"GRGRGRGRGRGRGRGRGRGR"

{{12, 1}, {14, 3}, {16, 5}, {18, 7}, {20, 9}}
{{4, 1}, {8, 5}, {12, 9}, {16, 13}, {20, 17}}
{{2, 3}, {8, 5}, {10, 11}, {16, 13}, {18, 19}}
{{2, 1}, {10, 7}, {12, 9}, {18, 13}, {20, 15}}
{{2, 1}, {6, 3}, {8, 5}, {16, 11}, { 20, 17}}
{}
{}

DavidC
fuente
2

Mathematica 134 o 124

Dependiendo de cómo cuente "Transponer []", que en Mathematica es solo un carácter (sin representación aquí). Espacios añadidos para mayor claridad.

G = 0; R = 1; 
x_~ d ~ y__:= Transpose[Position[Symbol /@ Characters@x - PadLeft[{}, 20, {y}], #, 1] &
                                                                                 /@ {1, -1}]
f = SortBy[{d[#, 0, 1], d[#, 1, 0]}, Length][[1]] &

Muestra:

f@"GGGGGGGGGGRRRRRRRRRR"
f@"GGRRGGRRGGRRGGRRGGRR"
f@"RRGGGGRRRRGGGGRRRRGG"
f@"GRRGRGGGGRRRGGGGRRRR"
f@"GRGGGRRRRGGGRGRRGGRR"
f@"RGRGRGRGRGRGRGRGRGRG"
f@"GRGRGRGRGRGRGRGRGRGR"

Salida

{{{11}, {2}}, {{13}, {4}}, {{15},  {6}}, {{17},  {8}}, {{19}, {10}}}
{{{3},  {2}}, {{7},  {6}}, {{11}, {10}}, {{15}, {14}}, {{19}, {18}}}
{{{1},  {4}}, {{7},  {6}}, {{9},  {12}}, {{15}, {14}}, {{17}, {20}}}
{{{2},  {1}}, {{10}, {7}}, {{12},  {9}}, {{18}, {13}}, {{20}, {15}}}
{{{2},  {1}}, {{6},  {3}}, {{8},   {5}}, {{16}, {11}}, {{20}, {17}}}
{}
{}
Dr. belisario
fuente
Codificación muy económica. Buen uso de funciones puras.
DavidC
@dude Gracias :). Estoy seguro de que PadLeft[{}, 20, {y}], #, 1]se puede comprimir un poco más
Dr. belisarius
2

Javascript - 173 caracteres

a=prompt(w=[[],[]]).split('');for(i=a.length,f=a[0];i--;)if(i%2<1&&a[i]!=f)w[0].push(i);else if(i%2>0&&a[i]==f)w[1].push(i);for(i=w[0].length;i--;)alert(w[0][i]+','+w[1][i])

Un gran desafío, me mantuvo ocupado por algún tiempo.
Aquí los resultados de los códigos para los casos de prueba:

GGGGGGGGGGRRRRRRRRRR: [10, 1] [12, 3] [14, 5] [16, 7] [18, 9]
GGRRGGRRGGRRGGRRGGRR: [ 2, 1] [ 6, 5] [10, 9] [14,13] [18,17]
RRGGGGRRRRGGGGRRRRGG: [ 2, 1] [ 4, 7] [10, 9] [12,15] [18,17]
GRRGRGGGGRRRGGGGRRRR: [ 2, 3] [ 4, 5] [10, 7] [16,13] [18,15]
GRGGGRRRRGGGRGRRGGRR: [ 6, 3] [ 8, 9] [12,11] [14,13] [18,17]
RGRGRGRGRGRGRGRGRGRG:
codeporn
fuente
1

PHP - 34 movimientos - 193 caracteres

$l=strlen($a=$_GET["a"]);$n=$a[0]=="R"?"G":"R";while($i<$l){if($a[++$i]!=$n){echo$o."
";$o=$a=substr($a,0,$i).$n.preg_replace("/".$n."/",$n=="R"?"G":"R",substr($a,$i+1),1);}$n=$n=="R"?"G":"R";}

Todavía podría intentar mejorar esto ...

red_green.php?a=GGGGGGGGGGRRRRRRRRRR

GRGGGGGGGGGRRRRRRRRR
GRGRGGGGGGGGRRRRRRRR
GRGRGRGGGGGGGRRRRRRR
GRGRGRGRGGGGGGRRRRRR
GRGRGRGRGRGGGGGRRRRR
GRGRGRGRGRGRGGGGRRRR
GRGRGRGRGRGRGRGGGRRR
GRGRGRGRGRGRGRGRGGRR
GRGRGRGRGRGRGRGRGRGR
Aurel300
fuente
podría ser mejor usarlo $argv[0], ahorrándote 2 bytes / cada uno. Y será más válido, ya $argvque a menudo se usa para la entrada a través de CMD
RedClover