Evolução do 'x'


15

Dado é um quadro de tamanho variável com um tamanho máximo de 5 vezes 5 campos. Cada campo pode ser preenchido com um 'x'. Se não for preenchido com um 'x', será preenchido com um 'o'.

O estado inicial de cada quadro é dado (veja abaixo). Em cada tabuleiro, 10 rodadas devem ser jogadas (no máximo, condições: veja abaixo) e a evolução do x deve ser observada.

Uma rodada funciona da seguinte maneira:

  1. todo 'x' se espalha para campos ortogonais limítrofes, mas desaparece
  2. cada vez que dois 'x' estão em um campo, eles se neutralizam

A evolução de todos os 'x' em cada rodada deve acontecer simultaneamente. Exemplo:

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

A cada rodada de evolução, você precisa ver se o quadro é esvaziado de 'x'. Se não estiver vazio, um padrão de repetição pode estar presente. Se esse também não for o caso, desistimos da análise da evolução. Além disso, você deve imprimir a porcentagem máxima de x campos para cada quadro inicial (arredondado para números inteiros).

Entrada:

Os dados de entrada podem ser encontrados aqui (Pastebin) Estes dados contêm 100 estados iniciais. Como já mencionado, as placas variam em tamanho. O número de linhas é indicado com o número n de 1 a 5, seguido por n linhas que contêm apenas 'x' e 'o', representam o padrão inicial. Cada linha de um tabuleiro possui 1 a 5 campos.

Resultado:

O resultado completo deve ser impresso, uma linha impressa para cada quadro inicial, da seguinte forma:

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

Exemplos:

Exemplo 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

Exemplo 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

Depois de oito dias, vou marcar a resposta de trabalho com o menor número de caracteres como o vencedor. Além disso, publicarei a saída correta para as 100 placas iniciais (entrada).

Você pode usar sua linguagem preferida (programação / script / qualquer que seja).

Diverta-se!

PS: Se você tiver dúvidas, não hesite em perguntar.

PPS: Com relação aos criadores originais: para pessoas capazes de falar alemão, a pergunta foi tirada de NÃO CLIQUE EM CASO DE NÃO QUERER SPOILERS aqui . Desde que o tempo oficial para concluir o desafio terminou, eu queria ver se alguém poderia encontrar uma solução curta e elegante.

22.04.2014:

Desafio feito! Vencedor marcado como aceito. Saída correta:

    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

Marque como código-golfe ou código-desafio, mas não ambos. (Deve ser um código de golfe neste caso).
user80551

1
Alguém deve mudar isso para um autômato celular bem definido. :-)
Justin

Respostas:


4

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

Edit: Um bug apareceu após uma das edições recentes, causando uma saída incorreta para placas vazias (a saída da suíte de testes estava OK). Como Round 0em determinado formato de saída pode significar apenas que pode haver placas vazias na entrada (embora nenhuma esteja na suíte de testes), o bug teve que ser corrigido. Solução rápida significa aumento da contagem de bytes (em 1, na verdade) - não é uma opção, é claro. Portanto, tive que jogar um pouco mais.

Corra com -p(+1 adicionado à contagem), lê STDIN. Requer 5.014 por causa do rmodificador de substituição.

(@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}

ie

# '-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
}

Uau, uma solução tão rápida. Estou surpreso. Como não estou familiarizado com o PERL (embora eu tenha instalado), como inicio seu script com meus dados de entrada?
plocks

2
@DevanLoper, por exemplo, perl -p x.pl < input.txtse os dados estiverem em um arquivo ou perl -p x.plalimentem linha por linha para testar uma entrada única (termine com ctrl-D( ctrl-Z)). Lembre-se de verificar se o seu perl é 5.014ou mais recente.
user2846289

Obrigado VadimR, agora ele roda. Mas tenho resultados diferentes em duas linhas relacionadas à porcentagem de preenchimento impresso. Mas isso pode ser erros de arredondamento.
plocks

1
@ DevanLoper, desculpe, é meu erro, a porcentagem é obtida da iteração anterior. Eu vou consertar isso em breve.
precisa saber é o seguinte

1
Bug corrigido, + alguns bytes jogados fora. Os resultados dos testes correspondem aos do site vinculado. Tecnicamente, 11 rodadas são executadas, mas o estado da última rodada não é verificado nem usado. É tudo por uma questão de concisão. Coloquei condições de quebra de loop no início para capturar a 1 \n oentrada.
precisa saber é o seguinte

3

C # - 1164 caracteres

Esta é a minha primeira participação no code-golf, então seja indulgente ;-)

Eu sei, estou longe dos melhores resultados - realmente incrível por sinal!

Mas pensei em compartilhar minha solução em C # de qualquer maneira.

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

Somente as diretivas de uso já contam com 97 caracteres - então acho que será muito difícil conseguir o resto com menos de 200 caracteres.

É uma abordagem bastante iterativa, usando o LINQ em muitos lugares. Também incluí o download do arquivo de entrada e a gravação do arquivo de saída no código.

Aqui está uma versão um pouco mais legível:

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

1
Curto, mais curto, a solução de Ben. Você criou um tal micro de um pensamento solução em C # termos ...
Paul Facklam

2

J - 275 char

Oh, todas essas especificações de E / S! Uma pontuação tão vergonhosamente grande para J, no final. Recebe entrada no STDIN com uma nova linha à direita e assume que não há retornos de carro ( \r) na entrada. Aqui está o resultado de aplicá-lo ao arquivo de entrada de amostra na pergunta.

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: (posso adicionar uma explicação mais completa e amigável para o novato mais 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

A $:peça faz o corpo principal recuar sobre a entrada (uma forma terrivelmente inconveniente para J analisar), aplicando a @corrente em cada seção. nlinesencontra o número de linhas para o próximo quadro.

A ação em cada quadro (evolvex ) é clara: iterate(chamada ano golfe) constrói uma lista de cada iteração da simulação até atingirmos algo visto antes ou muitas etapas. Em seguida, percent@,.calcula a porcentagem de quadrado preenchido em cada resultado e formatexecuta algumas estatísticas ( statchamadas tno golfe) para descobrir como a simulação terminou, qual porcentagem foi a maior e assim por diante, antes de formatar tudo isso em uma sequência.

Finalmente, }:cuida de um pouco de lixo antes; joinln juntar todas as saídas individuais da placa em uma sequência separada por nova linha.


Oi algoritmshark, você poderia fornecer instruções sobre como iniciar seu script na linha de comando com um arquivo .txt como parâmetro de entrada? Obrigado!
plocks

1
@ DevanLoper Isso me lembra, eu esqueci de fazer a saída para stdout; adicionou essa correção. Ele deve funcionar a maneira padrão agora: jconsole golf.ijs < input.txt.
algorithmshark

Obrigado pela informação, mas ainda não imprime nenhuma saída para mim, mesmo com o seu código alterado.
plocks

@DevanLoper O problema parece ser o meu uso vcomo um nome, que por qualquer motivo não é permitido em scripts. (Eu estava executando o trecho no REPL.) Alterá-lo para aparece funcionar.
algorithmshark

@algoshark Poderia ser eu, mas ainda não consigo imprimir nada.
plocks
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.