Ewolucja „x”

15

Podana jest tablica o zmiennej wielkości z maksymalnym rozmiarem 5 razy 5 pól. Każde pole kann musi być wypełnione znakiem „x”. Jeśli nie jest wypełniony „x”, jest wypełniony „o”.

Podany jest stan początkowy każdej planszy (patrz poniżej). Na każdej planszy należy rozegrać 10 rund (maksymalnie, warunki: patrz poniżej) i obserwować ewolucję x.

Jedna runda działa w następujący sposób:

  1. każde „x” rozprzestrzenia się na pola graniczące z ortogonalnie, ale samo znika
  2. za każdym razem, gdy dwa „x” znajdują się na jednym polu, wzajemnie się neutralizują

Ewolucja wszystkich „x” w każdej rundzie musi odbywać się jednocześnie. Przykład:

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

Z każdą rundą ewolucji musisz sprawdzić, czy tablica zostanie opróżniona z „x”. Jeśli nie jest pusty, może występować powtarzalny wzór. Jeśli tak nie jest, rezygnujemy z analizy ewolucji. Dodatkowo musisz wydrukować maksymalny procent x pól dla każdej planszy początkowej (zaokrąglony w dół do liczb całkowitych).

Wejście:

Dane wejściowe można znaleźć tutaj (Pastebin) Dane te zawierają 100 stanów początkowych. Jak już wspomniano, deski różnią się rozmiarem. Liczbę wierszy podano liczbą n od 1 do 5, a następnie n wierszy zawierających tylko „x” i „o” reprezentują wzorzec początkowy. Każdy rząd planszy ma od 1 do 5 pól.

Wynik:

Należy wydrukować pełny wynik, jeden wydrukowany rząd dla każdej planszy startowej w następującej formie:

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

Przykłady:

Przykład 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

Przykład 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

Po ośmiu dniach zaznaczę roboczą odpowiedź jako najmniej zwycięskich postaci. Dodatkowo opublikuję poprawne dane wyjściowe dla 100 kart startowych (dane wejściowe).

Możesz użyć preferowanego języka (programowania / skryptów / cokolwiek).

Baw się dobrze!

PS: Jeśli masz pytania, możesz je zadać.

PPS: W odniesieniu do oryginalnych twórców: Dla osób mówiących po niemiecku pytanie pochodzi od NIE KLIKNIJ, JEŚLI NIE CHCESZ SPOILERÓW tutaj . Ponieważ oficjalny czas na ukończenie wyzwania dobiegł końca, chciałem sprawdzić, czy ktoś może wymyślić krótkie i eleganckie rozwiązanie.

22.04.2014:

Wyzwanie gotowe! Zwycięzca oznaczony jako zaakceptowany. Prawidłowa wydajność:

    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
stada
źródło
Oznacz jako kod-golf lub kod-wyzwanie, ale nie oba. (W tym przypadku powinien to być golf golfowy).
user80551
1
Ktoś powinien zmienić to w dobrze zdefiniowany automat komórkowy. :-)
Justin

Odpowiedzi:

4

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

Edycja: błąd pojawił się po jednej z ostatnich edycji, powodując nieprawidłowe dane wyjściowe dla pustych płyt (wynik zestawu testów był OK). OdRound 0 w danym formacie wyjściowym może oznaczać tylko to, że na wejściu mogą znajdować się puste płyty (choć żadnej nie ma w pakiecie testowym), błąd musiał zostać naprawiony. Szybka poprawka oznacza zwiększenie liczby bajtów (właściwie o 1) - oczywiście nie jest to opcja. Dlatego musiałem pograć trochę bardziej w golfa.

Uruchom z -p(+1 dodane do zliczenia), czyta ze STDIN. Wymaga 5.014 z powodu rmodyfikatora podstawienia.

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

to znaczy

# '-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
}
użytkownik 2846289
źródło
Wow, rozwiązanie tak szybkie. Jestem zaskoczony. Ponieważ nie znam PERL-a (mam go już zainstalowany), w jaki sposób uruchomić skrypt ze swoimi danymi wejściowymi?
plocks
2
@DevanLoper, np. perl -p x.pl < input.txtJeśli dane znajdują się w pliku, lub podaje perl -p x.plwiersz po wierszu, aby przetestować pojedynczy wpis (zakończ za pomocą ctrl-D( ctrl-Z)). Pamiętaj, aby sprawdzić, czy Twój perl jest 5.014nowszy.
user2846289
Dzięki VadimR, teraz działa. Ale mam różne wyniki w dwóch wierszach dotyczące wydrukowanego procentu wypełnienia. Ale to mogą być błędy zaokrąglania.
ploki
1
@DevanLoper, przepraszam, to mój błąd, procent pochodzi z poprzedniej iteracji. Naprawię to wkrótce.
user2846289
1
Naprawiono błąd, wyrzucono niektóre bajty. Wyniki testów są zgodne z wynikami z połączonej witryny. Technicznie jest przeprowadzanych 11 rund, ale stan ostatniej rundy nie jest sprawdzany ani używany. To wszystko dla zwięzłości. Na początku umieściłem warunki przerywania pętli, aby złapać 1 \n odane wejściowe.
user2846289
3

C # - 1164 znaków

To mój pierwszy udział w code-golfie, więc proszę o pobłażanie ;-)

Wiem, że daleko mi do najlepszych wyników - nawiasem mówiąc, naprawdę niesamowitych!

Ale myślałem, że i tak podzielę się moim rozwiązaniem w C #.

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

Same dyrektywy używające już liczą 97 znaków - więc myślę, że osiągnięcie reszty w ciągu mniej niż 200 znaków będzie dość trudne.

Jest to dość iteracyjne podejście, wykorzystujące LINQ w wielu miejscach. Dołączyłem również pobieranie pliku wejściowego i zapisywanie pliku wyjściowego w kodzie.

Oto jedna nieco bardziej czytelna wersja:

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
źródło
1
Krótko, krócej, rozwiązanie Bena. Stworzyliście taką mikro rozwiązanie, myśląc w kategoriach C # ...
Paul Facklam
2

J - 275 znaków

Och, wszystkie te specyfikacje I / O! W końcu taki wstydliwie wysoki wynik dla J. Pobiera dane wejściowe STDIN z końcowym znakiem nowej linii i zakłada, że \rw danych wejściowych nie ma żadnych znaków powrotu karetki ( ). Oto wynik zastosowania go do przykładowego pliku wejściowego w pytaniu.

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: (Mogę dodać dokładniejsze i bardziej przyjazne dla J wyjaśnienie później).

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

Ta $:część powoduje, że główny korpus powraca nad wejściem (okropnie niewygodna forma dla parsowania J), nakładając @łańcuch połączeniowy na każdą sekcję. nlinesznajduje liczbę linii dla następnej planszy.

Akcja na każdej planszy ( evolvex) jest zgrabna: iterate(wywoływana aw golfie) tworzy listę każdej iteracji symulacji, dopóki nie trafimy ani na coś widocznego przed, ani na zbyt wiele kroków. Następnie percent@,.oblicza procent wypełnionego kwadratu w każdym wyniku i formaturuchamia niektóre statystyki ( stattzwt w golfie), aby dowiedzieć się, jak zakończyła się symulacja, który procent był największy i tak dalej, przed sformatowaniem tego wszystkiego w ciąg.

Wreszcie, }:zajmuje się niektórymi śmieciami, zanim ; joinlnpołączy wszystkie poszczególne dane wyjściowe płyty w jeden ciąg rozdzielony znakiem nowej linii.

algorytmshark
źródło
Cześć algorytmshark, czy możesz podać instrukcje dotyczące uruchamiania skryptu z wiersza polecenia z plikiem .txt jako parametrem wejściowym? Dzięki!
plock
1
@DevanLoper To mi przypomina, że ​​zapomniałem zrobić to na standardowe wyjście; dodał tę poprawkę. To powinno działać w standardowy sposób teraz: jconsole golf.ijs < input.txt.
algorytmshark
Dzięki za informacje, ale nadal nie drukuje dla mnie żadnych danych wyjściowych, nawet po zmianie kodu.
plock
@DevanLoper Problemem wydaje się być moje użycie vjako nazwy, co z jakiegokolwiek powodu nie jest dozwolone w skryptach. (Użyłem tego fragmentu w REPL.) Zmiana go na awyglądający na działającą.
algorytmshark
@algoshark To mógłbym być ja, ale nadal nie mogę go wydrukować.
plock