Evolución de la 'x'

15

Dado es un tablero de tamaño variable con un tamaño máximo de 5 veces 5 campos. Cada campo puede llenarse con una 'x'. Si no se llena con una 'x', se llena con una 'o'.

Se da el estado inicial de cada tablero (ver más abajo). Con cada tablero, se deben jugar 10 rondas (como máximo, condiciones: ver más abajo) y se debe observar la evolución de la x.

Una ronda funciona de la siguiente manera:

  1. cada 'x' se extiende a campos que bordean ortogonalmente, pero desaparece
  2. cada vez que dos 'x' están en un campo, se neutralizan entre sí

La evolución de todas las 'x' en cada ronda tiene que suceder simultáneamente. Ejemplo:

    o o o            o x o
    o x o     ->     x o x
    o o o            o x o

Con cada ronda de evolución, tienes que ver si el tablero se vacía de 'x'. Si no está vacío, podría estar presente un patrón repetitivo. Si este tampoco es el caso, renunciamos al análisis de la evolución. Además, debe imprimir el porcentaje máximo de campos x para cada tablero inicial (redondeado a números enteros).

Entrada:

Los datos de entrada se pueden encontrar aquí (Pastebin). Estos datos contienen 100 estados iniciales. Como ya se mencionó, las tablas varían en tamaño. El número de filas se indica con el número n del 1 al 5, seguido de n filas que contienen solo 'x' y 'o', representan el patrón inicial. Cada fila de un tablero tiene de 1 a 5 campos.

Salida:

El resultado completo debe imprimirse, una fila impresa para cada tablero inicial en el siguiente formulario:

    Round {0-10}: {repetition/empty/giveup}, {0-100} percent maximum-fill

Ejemplos:

Ejemplo 1:

    Input: 2       Starting state: x o x
           xox                     x x
           xx

                          Round 1: x x o
                                   o x

                          Round 2: x o x
                                   o x

                          Round 3: o x o
                                   o o

                          Round 4: x o x   -> The pattern repeats:
                                   o x        It is the same as in round 2,
                                              therefore we stop. Maximum fill was
                                              in the starting state with four times 'x'
                                              of 5 fields altogether,
                                              so we have 4/5 = 80 %.

    Output: Round 4: repetition, 80 percent maximum-fill

Ejemplo 2

    Input: 1       Starting state: x x
           xx                      

                          Round 1: x x    ->  We already have a repetition, because
                                              the pattern is the same as in the starting
                                              state. The board is always filled 100 %.

    Output: Round 1: repetition, 100 percent maximum-fill

Después del octavo día, marcaré la respuesta de trabajo con la menor cantidad de caracteres como el ganador. Además, publicaré la salida correcta para las 100 placas iniciales (entrada).

Puede usar su lenguaje preferido (programación / scripting / lo que sea).

¡Que te diviertas!

PD: Si tiene preguntas, no dude en preguntar.

PPS: con respecto a los creadores originales: para las personas capaces de hablar alemán, la pregunta se tomó de NO HAGA CLIC SI NO DESEA SPOILERS aquí . Dado que el tiempo oficial para completar el desafío ha terminado, quería ver si alguien podría llegar a una solución corta y elegante.

22.04.2014:

Desafío hecho! Ganador marcado como aceptado. Salida correcta:

    Round 10: giveup, 50 percent maximum-fill
    Round 5: empty, 66 percent maximum-fill
    Round 1: repetition, 100 percent maximum-fill
    Round 1: empty, 100 percent maximum-fill
    Round 4: repetition, 100 percent maximum-fill
    Round 4: repetition, 70 percent maximum-fill
    Round 2: repetition, 60 percent maximum-fill
    Round 4: empty, 88 percent maximum-fill
    Round 10: giveup, 50 percent maximum-fill
    Round 5: repetition, 80 percent maximum-fill
    Round 10: repetition, 80 percent maximum-fill
    Round 1: empty, 80 percent maximum-fill
    Round 3: repetition, 60 percent maximum-fill
    Round 4: repetition, 48 percent maximum-fill
    Round 9: empty, 41 percent maximum-fill
    Round 10: giveup, 92 percent maximum-fill
    Round 10: giveup, 53 percent maximum-fill
    Round 10: giveup, 66 percent maximum-fill
    Round 6: repetition, 50 percent maximum-fill
    Round 10: giveup, 88 percent maximum-fill
    Round 10: giveup, 76 percent maximum-fill
    Round 10: giveup, 68 percent maximum-fill
    Round 10: giveup, 40 percent maximum-fill
    Round 10: giveup, 100 percent maximum-fill
    Round 10: giveup, 71 percent maximum-fill
    Round 2: empty, 81 percent maximum-fill
    Round 6: repetition, 36 percent maximum-fill
    Round 10: giveup, 61 percent maximum-fill
    Round 10: giveup, 60 percent maximum-fill
    Round 4: repetition, 66 percent maximum-fill
    Round 10: giveup, 72 percent maximum-fill
    Round 3: empty, 80 percent maximum-fill
    Round 10: giveup, 50 percent maximum-fill
    Round 10: giveup, 83 percent maximum-fill
    Round 7: repetition, 37 percent maximum-fill
    Round 9: repetition, 85 percent maximum-fill
    Round 5: repetition, 40 percent maximum-fill
    Round 5: repetition, 60 percent maximum-fill
    Round 4: empty, 80 percent maximum-fill
    Round 10: giveup, 60 percent maximum-fill
    Round 4: repetition, 46 percent maximum-fill
    Round 6: repetition, 42 percent maximum-fill
    Round 10: giveup, 72 percent maximum-fill
    Round 4: repetition, 70 percent maximum-fill
    Round 4: repetition, 80 percent maximum-fill
    Round 6: repetition, 50 percent maximum-fill
    Round 4: repetition, 56 percent maximum-fill
    Round 10: giveup, 60 percent maximum-fill
    Round 10: giveup, 54 percent maximum-fill
    Round 10: giveup, 66 percent maximum-fill
    Round 2: repetition, 40 percent maximum-fill
    Round 2: repetition, 40 percent maximum-fill
    Round 6: repetition, 75 percent maximum-fill
    Round 7: empty, 85 percent maximum-fill
    Round 10: giveup, 50 percent maximum-fill
    Round 6: repetition, 70 percent maximum-fill
    Round 2: empty, 66 percent maximum-fill
    Round 1: empty, 66 percent maximum-fill
    Round 3: empty, 100 percent maximum-fill
    Round 3: empty, 66 percent maximum-fill
    Round 8: repetition, 42 percent maximum-fill
    Round 1: empty, 60 percent maximum-fill
    Round 2: repetition, 100 percent maximum-fill
    Round 2: repetition, 83 percent maximum-fill
    Round 4: repetition, 66 percent maximum-fill
    Round 6: repetition, 75 percent maximum-fill
    Round 4: empty, 66 percent maximum-fill
    Round 10: giveup, 61 percent maximum-fill
    Round 10: giveup, 56 percent maximum-fill
    Round 4: empty, 66 percent maximum-fill
    Round 6: repetition, 33 percent maximum-fill
    Round 3: empty, 57 percent maximum-fill
    Round 3: repetition, 100 percent maximum-fill
    Round 6: repetition, 73 percent maximum-fill
    Round 10: giveup, 50 percent maximum-fill
    Round 6: repetition, 50 percent maximum-fill
    Round 10: giveup, 73 percent maximum-fill
    Round 5: empty, 80 percent maximum-fill
    Round 10: giveup, 61 percent maximum-fill
    Round 3: repetition, 53 percent maximum-fill
    Round 10: giveup, 33 percent maximum-fill
    Round 10: giveup, 80 percent maximum-fill
    Round 10: giveup, 63 percent maximum-fill
    Round 10: giveup, 70 percent maximum-fill
    Round 10: giveup, 84 percent maximum-fill
    Round 7: repetition, 70 percent maximum-fill
    Round 10: repetition, 57 percent maximum-fill
    Round 10: giveup, 55 percent maximum-fill
    Round 6: repetition, 36 percent maximum-fill
    Round 4: repetition, 75 percent maximum-fill
    Round 10: giveup, 72 percent maximum-fill
    Round 10: giveup, 64 percent maximum-fill
    Round 10: giveup, 84 percent maximum-fill
    Round 10: giveup, 58 percent maximum-fill
    Round 10: giveup, 60 percent maximum-fill
    Round 10: giveup, 53 percent maximum-fill
    Round 4: repetition, 40 percent maximum-fill
    Round 4: empty, 40 percent maximum-fill
    Round 10: giveup, 50 percent maximum-fill
    Round 10: giveup, 68 percent maximum-fill
plocks
fuente
Etiqueta como code-golf o code-challenge pero no ambos. (Debería ser code-golf en este caso).
user80551
1
Alguien debería cambiar esto en un autómata celular bien definido. :-)
Justin

Respuestas:

4

Perl 308, 304, 305, 293, 264 , 262

Editar: un error se deslizó después de una de las ediciones recientes, causando resultados incorrectos para tableros vacíos (el resultado del conjunto de pruebas estuvo bien). Dado que Round 0en un formato de salida dado solo puede significar que puede haber tableros vacíos en la entrada (aunque ninguno está en el conjunto de pruebas), el error tuvo que repararse. La solución rápida significaba un aumento en el recuento de bytes (en 1, en realidad), no es una opción, por supuesto. Por lo tanto, tuve que jugar al golf un poco más.

Ejecutar con -p(+1 agregado al recuento), lecturas de STDIN. Requiere 5.014 debido al rmodificador de sustitución.

(@a,%h,$m)=('',map<>=~y/ox\n/\0!/rd,1..$_);for$n(0..10){$_="Round $n: ".($h{$_="@a"}++?repetition:(($.=100*y/!///y/ //c)<$m?$.:$m=$.)?giveup:empty).", $m percent maximum-fill\n";@a=/g/?map{$_=$a[$i=$_];y//!/cr&(s/.//r.P^P.s/.$//r^$a[$i+1]^$a[$i-1])}0..$#a:last}

es decir

# '-p' switch wraps code into the 'while(<>){....}continue{print}' loop, 
# which reads a line from STDIN into $_, executes '....' and prints contents 
# of $_. We use it to read board height and print current board's result.

# First line reads board's state into @a array, a line per element, at the same 
# time replacing 'o' with 'x00', 'x' with '!' and chomping trailing newlines. 
# '!' was chosen because it's just like 'x01' except 5th bit (which is not important)
# but saves several characters in source code.

# Note: array is prepended with an empty line, which automatically remains in this 
# state during evolution, but saves us trouble of checking if actual (any non-empty)
# line has neighboring line below.

# %h hash and $m hold seen states and maximum fill percentage for current board,
# they are initialized to undef i.e empty and 0.

(@a,%h,$m)=('',map<>=~y/ox\n/\0!/rd,1..$_);

# /
# Then do required number of evolutions:

for$n(0..10){

# Stringify board state, i.e. concatenate lines with spaces ($") as separators.
# Calculate fill percentage - divide number of '!' by number of non-spaces. 
# Note: using $. magick variable automatically takes care of rounding.
# Construct output string. It's not used if loop gets to next iteration. 
# Check if current state was already seen (at the same time add it to %h) 
# and if fill percentage is 0.

$_="Round $n: "
    .($h{$_="@a"}++?repetition:(($.=100*y/!///y/ //c)<$m?$.:$m=$.)?giveup:empty)
    .", $m percent maximum-fill\n";

# /
# Next is funny: if output string contains 'g' (of 'giveup' word), then evolve 
# further, otherwise break-out of the loop.

    @a=/g/
        ?map{

# Do evolution round. Act of evolution for a given line is none other than 
# XOR-ing 4 strings: itself shifted right, itself shifted left, line above, line 
# below. Result of this operation is truncated to original length using bitwise '&'. 
# Note, when shifting string right or left we prepend (append) not an ascii-0, 
# but 'P' character. It's shorter, and 4th and 6th bits will be annihilated anyway.

            $_=$a[$i=$_];
            y//!/cr
            &(s/.//r.P
            ^P.s/.$//r
            ^$a[$i+1]
            ^$a[$i-1])
        }0..$#a
        :last
}
usuario2846289
fuente
Wow, una solución tan rápida. Estoy asombrado. Como no estoy familiarizado con PERL (aunque lo tengo instalado), ¿cómo comienzo su script con mis datos de entrada?
bloquea el
2
@DevanLoper, por ejemplo, perl -p x.pl < input.txtsi los datos están en un archivo, o si se perl -p x.plalimentan línea por línea para probar una sola entrada (terminar con ctrl-D( ctrl-Z)). Recuerde verificar su perl es 5.014o más reciente.
user2846289
Gracias VadimR, ahora se ejecuta. Pero tengo resultados diferentes en dos líneas con respecto al porcentaje de relleno impreso. Pero eso podría ser errores de redondeo.
bloquea el
1
@DevanLoper, lo siento, es mi error, el porcentaje se toma de la iteración anterior. Lo arreglaré pronto.
user2846289
1
Error solucionado, + algunos bytes descartados. Los resultados de las pruebas coinciden con los del sitio vinculado. Técnicamente, se ejecutan 11 rondas, pero el estado de la última ronda no se verifica ni se utiliza. Todo es por brevedad. Coloqué condiciones de ruptura de bucle al principio para captar la 1 \n oentrada.
user2846289
3

C # - 1164 caracteres

Esta es mi primera participación en code-golf, así que por favor sea indulgente ;-)

Lo sé, estoy lejos de los mejores resultados, por cierto, ¡realmente increíble!

Pero pensé que compartiría mi solución en C # de todos modos.

using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;class Program{static void Main(string[] args){new WebClient().DownloadFile("http://mc.capgemini.de/challenge/in.txt",@"D:\in.txt");var a=File.ReadAllLines(@"D:\in.txt");int l=0;while(l<a.Length){int n=Int32.Parse(a[l]);var b=a.Skip(l+1).Take(n).ToArray();var f=new List<string[]>{b};var d=0;string g=null;while(d<10){var s=f.Last();if(s.All(e=>e.All(c=>c=='o'))){g="empty";break;}var h=new string[n];for(int r=0;r<n;r++){var k="";for(int c=0;c<b[r].Length;c++){int x=0;try{if(s[r][c-1]=='x')x++;}catch{}try{if(s[r][c+1]=='x')x++;}catch{}try{if(s[r-1][c]=='x')x++;}catch{}try{if(s[r+1][c]=='x')x++;}catch{}k+=((x%2)==1)?'x':'o';}h[r]=k;}d++;f.Add(h);var w=false;for(int i=0;i<f.Count-1;i++){var m=f[i];if (!h.Where((t,y)=>t!=m[y]).Any())w=true;}if(w){g="repetition";break;}}if(d==10&&g==null)g="giveup";File.AppendAllLines(@"D:\out.txt",new[]{string.Format("Round {0}: {1}, {2} percent maximum-fill",d,g,f.Select(z=>{int t=0;int x=0;foreach(var c in z.SelectMany(s=>s)){t++;if(c=='x')x++;}return(int)Math.Floor((double)x/t*100);}).Concat(new[]{0}).Max())});l=l+n+1;}}}

Solo las directivas de uso ya cuentan 97 caracteres, así que creo que va a ser bastante difícil lograr el resto en menos de 200 caracteres.

Es un enfoque bastante iterativo, que utiliza LINQ en muchos lugares. También incluí la descarga del archivo de entrada y la escritura del archivo de salida en el código.

Aquí hay una versión un poco más legible:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;

class Program
{
    static void Main(string[] args)
    {
        // Download the file
        new WebClient().DownloadFile("http://mc.capgemini.de/challenge/in.txt", @"D:\in.txt");
        // Read of lines of downloaded file
        var a = File.ReadAllLines(@"D:\in.txt");
        // Line index in input file
        int l = 0;
        while (l < a.Length)
        {
            // Parse number of rows to take
            int n = Int32.Parse(a[l]);

            // Take the n rows
            var b = a.Skip(l + 1).Take(n).ToArray();
            var f = new List<string[]> { b };
            var d = 0;
            string g = null;
            while (d < 10)
            {
                // Last state consists only of o's? -> 
                var s = f.Last();
                if (s.All(e => e.All(c => c == 'o')))
                {
                    g = "empty";
                    break;
                }
                // In h we will build up the new state
                var h = new string[n];
                // Loop through all rows of initial state
                for (int r = 0; r < n; r++)
                {
                    // This is our new row we will build up for the current state
                    var k = "";
                    // Count number of orthogonal adjacent x's
                    // And catch potential OutOfRangeExceptions
                    for (int c = 0; c < b[r].Length; c++)
                    {
                        int x = 0;
                        try { if (s[r][c - 1] == 'x') x++; }
                        catch { }
                        try { if (s[r][c + 1] == 'x') x++; }
                        catch { }
                        try { if (s[r - 1][c] == 'x') x++; }
                        catch { }
                        try { if (s[r + 1][c] == 'x') x++; }
                        catch { }
                        // Is number of adjacent x's odd? -> character will be 'x'
                        // otherwise -> 'o'
                        k += ((x % 2) == 1) ? 'x' : 'o';
                    }
                    // Add the new row to the current state
                    h[r] = k;
                }
                // Increase round count
                d++;
                // Add the new state to our state collection
                f.Add(h);
                // Now check, whether it is a repetition by comparing the last state (h) with all other states
                bool w = false;
                for (int i = 0; i < f.Count - 1; i++)
                {
                    var m = f[i];
                    if (!h.Where((t, y) => t != m[y]).Any())
                        w = true;
                }
                if (w)
                {
                    g = "repetition";
                    break;
                }
            }
            // Check whether we reached maximum AND the last round wasn't a repetition
            if (d == 10 && g == null)
                g = "giveup";
            // Now we append the final output row to our text file
            File.AppendAllLines(@"D:\out.txt",
                new[]
                    {
                        string.Format("Round {0}: {1}, {2} percent maximum-fill",
                        d,
                        g,
                        // Here we select all rates of x's per state
                        // and then grab the maximum of those rates
                        f.Select(z =>
                            {
                                int t=0;
                                int x=0;
                                foreach (char c in z.SelectMany(s => s))
                                {
                                    t++;
                                    if(c=='x')
                                        x++;
                                }
                                return (int) Math.Floor((double) x / t *100);
                            }).Concat(new[] {0}).Max())
                    });
            // finally we shift our index to the next (expected) number n in the input file
            l = l + n + 1;
        }
    }
}
Ben Sch
fuente
1
Corto, más corto, la solución de Ben. Has creado una solución tan
pequeña
2

J - 275 char

¡Oh, todas estas especificaciones de E / S! Una puntuación tan vergonzosamente grande para J, al final. Toma información en STDIN con una nueva línea final y asume que no hay ningún retorno de carro ( \r) en la entrada. Aquí está el resultado de aplicarlo al archivo de entrada de muestra en la pregunta.

stdout;,&LF&.>}:(".@{~&0(('Round ',":@(#->/@t),': ',(empty`repetition`giveup{::~2<.#.@t=.11&=@#,0={:),', ',' percent maximum-fill',~0":>./)@(100*1&=%&(+/"1)_&~:)@,.@(a=:(a@,`[@.(e.~+.10<#@[)(_*_&=)+[:~:/((,-)(,:|.)0 1)|.!.0=&1){:)@,:@('ox'&i.^_:)@{.;$: ::]@}.)}.)];._2[1!:1]3

Ungolfed: (puedo agregar una explicación más completa y amigable para los novatos más tarde).

input   =: ];._2 [ 1!:1]3
convert =: 'ox'&i. ^ _:               NB. 'x'=>1  'o'=>0  else=>infinity
spread  =: ((,-)(,:|.)0 1) |.!.0 =&1  NB. x spreading outwards
cover   =: (_*_&=) + [: ~:/ spread    NB. collecting x`s and removing tiles not on board
iterate =: (iterate@, ` [ @. (e.~ +. 10<#@[) cover) {:
percent =: 100 * 1&= %&(+/"1) _&~:    NB. percentage of x at each step
max     =: 0 ": >./
stat    =: 11&=@# , 0={:              NB. information about the simulation
ending  =: empty`repetition`giveup {::~ 2 <. #.@stat   NB. how simulation ended
round   =: ": @ (# - >/@stat)         NB. round number
format  =: 'Round ', round, ': ', ending, ', ', ' percent maximum-fill',~ max
evolvex =: format @ percent@,. @ iterate@,: @ convert
joinln  =: ,&LF &.>
nlines  =: ". @ {~&0
remain  =: }.
stdout ; joinln }: (nlines (evolvex@{. ; $: ::]@}.) remain) input

La $:parte hace que el cuerpo principal recurra sobre la entrada (una forma terriblemente inconveniente para que J analice), aplicando la @cadena de margaritas sobre cada sección.nlinesencuentra el número de líneas para el próximo tablero.

La acción en cada tablero ( evolvex) es clara: iterate(llamada aen el golf) construye una lista de cada iteración de la simulación hasta que alcanzamos algo visto antes o demasiados pasos. Luego percent@,.calcula el porcentaje de cuadrado lleno en cada resultado y formatejecuta algunas estadísticas ( statllamadast en el campo de golf) para descubrir cómo terminó la simulación, qué porcentaje fue el mayor, y así sucesivamente, antes de formatear todo eso en una cadena.

Finalmente, }:se ocupa de un poco de basura antes de ; joinlnunir todas las salidas de la placa individual en una cadena separada por una nueva línea.

Algoritmo de tiburón
fuente
Hola Algoritmo de tiburón, ¿podría proporcionar instrucciones sobre cómo iniciar su secuencia de comandos desde la línea de comandos con un archivo .txt como parámetro de entrada? ¡Gracias!
bloquea el
1
@DevanLoper Eso me recuerda que olvidé hacer que salga a stdout; agregó esa corrección. Se debe trabajar la forma estándar ahora: jconsole golf.ijs < input.txt.
algorithmshark
Gracias por la información, pero todavía no imprime ningún resultado para mí, incluso con su código cambiado.
bloquea el
@DevanLoper El problema parece ser mi uso vcomo nombre, que por cualquier razón no está permitido en los scripts. (Había estado ejecutando el fragmento en el REPL.) Cambiarlo aparece funcionar.
algorithmshark
@algoshark Podría ser yo, pero aún no puedo conseguir que me imprima nada.
bloquea el