Evolution du «x»

15

Donné est un tableau de taille variable avec une taille maximale de 5 fois 5 champs. Chaque champ peut être rempli d'un «x». S'il n'est pas rempli d'un «x», il est rempli d'un «o».

L'état de départ de chaque planche est donné (voir ci-dessous). Avec chaque plateau, 10 tours doivent être joués (au maximum, conditions: voir ci-dessous) et l'évolution du x doit être surveillée.

Un tour fonctionne de la manière suivante:

  1. chaque «x» se propage à des champs bordant orthogonalement, mais disparaît
  2. chaque fois que deux «x» sont sur un champ, ils se neutralisent

L'évolution de tous les «x» à chaque tour doit se produire simultanément. Exemple:

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

À chaque tour d'évolution, vous devez voir si le plateau se vide de «x». S'il n'est pas vide, un motif répétitif pourrait être présent. Si ce n'est pas non plus le cas, nous renonçons à l'analyse de l'évolution. De plus, vous devez imprimer le pourcentage maximum de champs x pour chaque planche de départ (arrondi aux nombres entiers).

Contribution:

Les données d'entrée peuvent être trouvées ici (Pastebin) Ces données contiennent 100 états de départ. Comme déjà mentionné, les planches varient en taille. Le nombre de lignes est indiqué avec le nombre n de 1 à 5, suivi de n lignes qui ne contiennent que «x» et «o», représentent le modèle de départ. Chaque ligne d'une planche a 1 à 5 champs.

Production:

Le résultat complet doit être imprimé, une ligne imprimée pour chaque planche de départ sous la forme suivante:

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

Exemples:

Exemple 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

Exemple 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

Après huit jours, je marquerai la réponse de travail avec le moins de caractères comme gagnant. De plus, je publierai la sortie correcte pour les 100 planches de départ (entrée).

Vous pouvez utiliser votre langage préféré (programmation / scripting / autre).

S'amuser!

PS: Si vous avez des questions, n'hésitez pas à demander.

PPS: En ce qui concerne les créateurs originaux: Pour les personnes capables de parler allemand, la question est tirée de NE PAS CLIQUER SI VOUS NE VOULEZ PAS DE SPOILERS ici . Puisque le temps officiel pour terminer le défi est terminé, je voulais voir si quelqu'un pourrait trouver une solution courte et élégante.

22.04.2014:

Défi terminé! Le gagnant est marqué comme accepté. Sortie correcte:

    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
chaussettes
la source
Veuillez marquer comme code-golf ou code-challenge mais pas les deux. (Il doit s'agir de code-golf dans ce cas).
user80551
1
Quelqu'un devrait changer cela en un automate cellulaire bien défini. :-)
Justin

Réponses:

4

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

Edit: Un bug s'est glissé après l'une des modifications récentes, provoquant une sortie incorrecte pour les tableaux vides (la sortie de la suite de tests était OK). Étant Round 0donné qu'un format de sortie donné peut signifier uniquement qu'il peut y avoir des cartes vides dans l'entrée (bien qu'aucune ne soit dans la suite de tests), le bogue a dû être corrigé. Une correction rapide signifiait une augmentation du nombre d'octets (de 1, en fait) - pas une option, bien sûr. J'ai donc dû jouer un peu plus au golf.

Exécuter avec -p(+1 ajouté pour compter), lit à partir de STDIN. Nécessite 5.014 en raison du rmodificateur de substitution.

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

c'est à dire

# '-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
}
user2846289
la source
Wow, une solution si rapide. Je suis étonné. Comme je ne connais pas PERL (je l'ai installé cependant), comment puis-je démarrer votre script avec mes données d'entrée?
plocks
2
@DevanLoper, par exemple perl -p x.pl < input.txtsi les données se trouvent dans un fichier ou perl -p x.plet alimentez ligne par ligne pour tester une seule entrée (terminez par ctrl-D( ctrl-Z)). N'oubliez pas de vérifier que votre perl est 5.014ou plus récent.
user2846289
Merci VadimR, maintenant il fonctionne. Mais j'ai un résultat différent sur deux lignes concernant le pourcentage de remplissage imprimé. Mais cela pourrait être des erreurs d'arrondi.
plocks
1
@DevanLoper, désolé, c'est mon erreur, le pourcentage est tiré de l'itération précédente. Je vais le réparer bientôt.
user2846289
1
Bug corrigé, + quelques octets jetés. Les résultats des tests correspondent à ceux du site lié. Techniquement, 11 tours sont exécutés, mais l'état du dernier tour n'est ni vérifié ni utilisé. C'est pour la brièveté. J'ai placé des conditions de rupture de boucle au début pour capturer l' 1 \n oentrée.
user2846289
3

C # - 1164 caractères

C'est ma première participation au code-golf alors soyez indulgents ;-)

Je sais, je suis loin des meilleurs résultats - vraiment incroyable d'ailleurs!

Mais je pensais que je partagerais ma solution en C # de toute façon.

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

Seules les directives d'utilisation comptent déjà 97 caractères - donc je pense qu'il va être assez difficile de faire le reste en moins de 200 caractères.

Il s'agit d'une approche assez itérative, utilisant LINQ à de nombreux endroits. J'ai également inclus le téléchargement du fichier d'entrée et l'écriture du fichier de sortie dans le code.

Voici une petite version plus lisible:

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
la source
1
Court, plus court, la solution de Ben. Vous avez créé un tel micro d'une solution en pensant en termes C # ...
Paul Facklam
2

J - 275 caractères

Oh, toutes ces spécifications d'E / S! Un score si honteusement grand pour J, à la fin. Prend l'entrée sur STDIN avec une nouvelle ligne de fin et suppose qu'il n'y a pas de retour chariot ( \r) dans l'entrée. Voici le résultat de son application à l'exemple de fichier d'entrée de la question.

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: (Je peux ajouter une explication plus approfondie et conviviale pour les débutants plus tard.)

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 $:partie fait rentrer le corps principal sur l'entrée (une forme terriblement gênante pour J à analyser), en appliquant la @connexion en guirlande sur chaque section. nlinestrouve le nombre de lignes pour le tableau suivant.

L'action sur chaque planche ( evolvex) est nette: iterate(appelée adans le golf) construit une liste de chaque itération de la simulation jusqu'à ce que nous frappions quelque chose vu avant ou trop d'étapes. Calcule ensuite percent@,.le pourcentage de carré rempli dans chaque résultat et formatexécute des statistiques ( stat, appelées tdans le golf) pour comprendre comment la simulation s'est terminée, quel pourcentage était le plus élevé, etc., avant de formater tout cela dans une chaîne.

Enfin, }:prend soin de quelques ordures avant de ; joinlnjoindre toutes les sorties de la carte individuelle dans une chaîne séparée par des retours à la ligne.

algorithmshark
la source
Bonjour algorithmshark, pourriez-vous s'il vous plaît fournir des instructions sur la façon de démarrer votre script à partir de la ligne de commande avec un fichier .txt comme paramètre d'entrée? Merci!
plocks
1
@DevanLoper Cela me rappelle, j'ai oublié de le faire sortir sur stdout; a ajouté cette correction. Il devrait maintenant fonctionner de façon standard: jconsole golf.ijs < input.txt.
algorithmshark
Merci pour l'info, mais cela n'imprime toujours aucune sortie pour moi, même avec votre code modifié.
plocks
@DevanLoper Le problème semble être mon utilisation en vtant que nom, qui pour une raison quelconque n'est pas autorisé dans les scripts. (J'avais exécuté l'extrait dans le REPL.) Le modifier en asemble fonctionner.
algorithmshark
@algoshark Ce pourrait être moi, mais je ne parviens toujours pas à l'imprimer.
plocks