Эволюция «х»

15

Дается доска переменного размера с максимальным размером 5 раз 5 полей. Каждое поле может быть заполнено знаком «х». Если это не заполнено 'x', это заполнено 'o'.

Начальное состояние каждой доски дается (см. Ниже). На каждой доске необходимо сыграть 10 раундов (при макс. Условиях: см. Ниже) и следить за развитием x.

Один раунд работает следующим образом:

  1. каждый «х» распространяется на ортогонально граничащие поля, но исчезает сам по себе
  2. каждый раз, когда два «х» находятся на одном поле, они нейтрализуют друг друга

Эволюция всех «х» в каждом раунде должна происходить одновременно. Пример:

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

С каждым раундом эволюции вы должны видеть, очищается ли доска от «х». Разве это не пусто, повторяющийся узор может присутствовать. Если это также не так, мы отказываемся от анализа эволюции. Кроме того, вы должны распечатать максимальный процент полей x для каждой стартовой доски (округленный до целых чисел).

Входные данные:

Входные данные можно найти здесь (Pastebin). Эти данные содержат 100 начальных состояний. Как уже упоминалось, платы различаются по размеру. Количество строк указано с номером n от 1 до 5, за которым следуют n строк, которые содержат только «x» и «o», которые представляют начальный шаблон. Каждый ряд доски имеет от 1 до 5 полей.

Выход:

Полный результат должен быть распечатан, по одной печатной строке для каждой стартовой доски в следующем виде:

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

Примеры:

Пример 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

Пример 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

После восьми дней я отмечу рабочий ответ с наименьшим количеством символов как победитель. Кроме того, я опубликую правильный вывод для 100 стартовых досок (вход).

Вы можете использовать предпочитаемый вами язык (программирование / скриптинг).

Веселиться!

PS: Если у вас есть вопросы, не стесняйтесь спрашивать.

PPS: В отношении оригинальных создателей: для людей, способных говорить по-немецки, был задан вопрос НЕ НАЖИМАЙТЕ, ЕСЛИ ВЫ НЕ ХОТИТЕ СПОЙЛЕРОВ здесь . Поскольку официальное время для завершения задачи истекло, я хотел посмотреть, не может ли кто-нибудь придумать короткое и элегантное решение.

22.04.2014:

Задача выполнена! Победитель отмечен как принятый. Правильный вывод:

    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
источник
Пожалуйста, отметьте как код-гольф или код-вызов, но не оба. (Это должен быть код-гольф в этом случае).
user80551
1
Кто-то должен изменить это в четко определенный клеточный автомат. :-)
Джастин

Ответы:

4

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

Редактировать: ошибка появилась после одного из недавних изменений, что привело к неправильному выводу для пустых досок (вывод набора тестов был в порядке). Поскольку Round 0в данном формате вывода может означать только то, что во входе могут быть пустые доски (хотя ни одна из них не входит в набор тестов), ошибку необходимо было исправить. Быстрое исправление означало увеличение количества байтов (на 1, на самом деле) - не вариант, конечно. Поэтому мне пришлось играть в гольф немного больше.

Запуск с -p(+1 добавлено к счету), читает из STDIN. Требуется 5.014 из-за rмодификатора замещения.

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

т.е.

# '-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
источник
Вау, решение так быстро. Я удивлен Так как я не знаком с PERL (хотя он у меня установлен), как мне запустить ваш скрипт с моими входными данными?
разносится
2
@DevanLoper, например, perl -p x.pl < input.txtесли данные находятся в файле, или perl -p x.plи строка за строкой для проверки отдельной записи (завершается с ctrl-D( ctrl-Z)). Не забудьте проверить ваш perl 5.014или новее.
user2846289
Спасибо VadimR, теперь он работает. Но у меня есть разные результаты в двух строках относительно напечатанного процента заполнения. Но это может быть ошибкой округления.
разносится
1
@DevanLoper, извините, это моя ошибка, процент взят из предыдущей итерации. Я исправлю это в ближайшее время.
user2846289
1
Исправлена ​​ошибка, + отбрасывались некоторые байты. Результаты тестов совпадают с результатами на связанном сайте. Технически выполняется 11 раундов, но состояние последнего раунда не проверяется и не используется. Это все для краткости. Я поместил условия прерывания цикла в начале, чтобы поймать 1 \n oввод.
user2846289
3

C # - 1164 символа

Это мое первое участие в Code-Golf, поэтому, пожалуйста, будьте снисходительны ;-)

Я знаю, я далек от лучших результатов - кстати, действительно потрясающе!

Но я все равно решил поделиться своим решением в 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;}}}

Только директивы using уже насчитывают 97 символов, так что я думаю, что достичь остальных будет менее чем за 200 символов.

Это довольно итеративный подход, использующий LINQ во многих местах. Я также включил загрузку входного файла и запись выходного файла в код.

Вот еще одна более читаемая версия:

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
Короче, короче, решение Бена. Вы создали такой микро-решения решения в терминах C # ...
Пол Facklam
2

J - 275 символов

Ох, все эти спецификации ввода / вывода! Такой позорно большой счет для J, в конце концов. Принимает ввод в STDIN с завершающим символом новой строки и предполагает, что \rво входе нет никаких возвратов каретки ( ). Вот результат применения его к образцу входного файла в вопросе.

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: (Я могу добавить более подробное и J-newbie-friendly объяснение позже.)

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

Эта $:часть заставляет основную часть проходить через вход (ужасно неудобная форма для анализа J), применяя @цепочку гирлянд к каждой секции. nlinesнаходит количество строк для следующей доски.

Действие на каждой доске ( evolvex) является аккуратным: iterate( вызывается aв гольфе) создает список каждой итерации симуляции, пока мы не натолкнемся на то, что видели ранее, или слишком много шагов. Затем percent@,.вычисляет процент заполненного квадрата в каждом результате и formatзапускает некоторую статистику ( statназываемую tв гольфе), чтобы выяснить, как закончилась симуляция, какой процент был наибольшим и т. Д., Прежде чем форматировать все это в строку.

Наконец, }:позаботится о некотором мусоре, прежде чем ; joinlnобъединит все отдельные выводы платы в одну строку, разделенную символом новой строки.

algorithmshark
источник
Привет алгоритм, не могли бы вы дать инструкции о том, как запустить ваш скрипт из командной строки с TXT-файлом в качестве входного параметра? Благодарность!
разносится
1
@DevanLoper Это напоминает мне, я забыл сделать вывод на стандартный вывод; добавил это исправление. Он должен работать стандартный способ в настоящее время: jconsole golf.ijs < input.txt.
алгоритмическая
Спасибо за информацию, но она все равно не распечатывает вывод для меня, даже если ваш код изменился.
разносится
@DevanLoper Проблема заключается в том, что я использую vимя в качестве имени, которое по какой-либо причине не разрешено в сценариях. (Я выполнял фрагмент в REPL.) Изменение его aна работает.
алгоритмистика
@algoshark Это может быть я, но я все еще не могу заставить его что-нибудь напечатать.
разносится