29

Задача соревнования:

Имеется двумерный массив N x N. Нужно написать функцию обхода двумерного массива змейкой от правого ребра. Пример на картинке.

введите сюда описание изображения


Пример двумерного массива:

На входе имеется следующий массив:

input = [[4, 3, 2, 1], [5, 6, 7, 8], [12, 11, 10, 9], [13, 14, 15, 16]]

На выходе одномерный массив после обхода:

output = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

Может использоваться любой язык.

Основное условие: функция должна работать корректно для любого равностороннего двумерного массива.

Указывать название языка в заголовке ответа и количество символов минифицированной версии функции через запятую.

Победителем станет тот, кто напишет ее за меньшее количество символов. За это он получает 300 репутации. Победитель определится через 2 недели (12 января).

Ответ автора не учитывается при выборе победителя. Желаю удачи :)

Таблица лидеров:

execute("ru.stackoverflow.com", 926927);
<script src="https://mayorovp.github.io/codegolf/table-8c505e68f1349e4c69e7.js"></script>

Победители:

1 место: Haskell - 39 (@АндрейNOP)

2 место: JavaScript - 40 (@Groxan)

3 место: Groovy - 42 (@Nick)

Всем огромное спасибо за участие и интересные решения ;)

  • 3
    Ну вот, опять - "меньшее количество символов" независимо от языка. Участвовать с C/C++ - никакого смысла... – Harry Dec 29 '18 at 17:52
  • @Harry, что вы предлагаете? Поменять условия и выбирать самое уникальное решение? :) –  Dec 29 '18 at 17:55
  • Я не предлагаю, а информирую :) Да и потом, зачем - уникальное? Например, самое быстрое :) – Harry Dec 29 '18 at 18:06
  • @Harry, спасибо, идея мне понравилась, поменяю правила) –  Dec 29 '18 at 18:11
  • 1
    Как вы планируете сравнивать различные решения (на разных языках) на скорость? ;) – MaxU - stand with Ukraine Dec 29 '18 at 18:14
  • 1
    @MaxU, пожалуй я вернусь к правилам кода-гольфа, как-то не подумал... Спасибо за замечание. –  Dec 29 '18 at 18:17
  • Подсчёт количества символов ведётся только для "прохода по массиву"? То есть учитывается ли ввод данных в массив, вывод массива на экран (и нужен ли он)? И ещё вопрос: N выбирается автором ответа? Если да, то допустимы ли N=0 и степени двойки? – cpp questions Dec 29 '18 at 18:43
  • @cppquestions, подсчет символов самой функции, ввод и вывод данных в массив не нужен. В примерах использовать функцию на заполненном массиве. N определяется автоматически, в зависимости от массива –  Dec 29 '18 at 18:45
  • @Let'ssayPie только символов тела функции? Можно ли тогда делать что-нибудь вне её? – cpp questions Dec 29 '18 at 18:52
  • @Let'ssayPie ну на C и C++, например, можно задефайнить всё что угодно вне функции и в теле функции оставить 1 символ, который препроцессор заменит на нужный код извне тела :) – cpp questions Dec 29 '18 at 18:54
  • @cppquestions, посмотрите пример с похожего соревнования –  Dec 29 '18 at 18:58
  • @MaxU Но ведь на длину текста он же как-то сравнивает? :) Я потому и предложил (не всерьез, кстати, потому и смайлик) скорость - что C/C++ при этом будет в заведомо выигрышном положении :) – Harry Dec 29 '18 at 19:19
  • связанный вопрос creating a spiral array in python? – jfs Dec 31 '18 at 15:51
  • Раз любой, тогда можно и несуществующий (пока) язык snake. В нём определёно префикс s, который решает вышеуказанную задачу. Код для прохождения массива NxN кодируется как sN – Adokenai Jan 01 '19 at 04:26
  • Тоже поддерживаю, т.к. задания, порой, интересные и соревновательный интерес подстёгивает, но на кол-во символов не каждый язык способен соревноваться – Isaev Jan 01 '19 at 17:57
  • @Isaev, чем каждый язык способен посоревноваться? –  Jan 01 '19 at 18:28
  • @Let'ssayPie Ни чем, наверное... В силу своей специфики, нельзя сравнивать несравнимое... Можно соревноваться в одном языке в чем угодно, но в разных только очень условно – Isaev Jan 01 '19 at 18:36
  • @PavelMayorov, таблица сломалась похоже – Андрей NOP Jan 03 '19 at 15:56
  • @АндрейNOP можешь сказать что именно там не работает? А также свой браузер. – Pavel Mayorov Jan 03 '19 at 16:20
  • @PavelMayorov, изначально тоже заметил поломку, неправильный рейтинг был, и у некоторых выводилось N/A. Но сейчас все в порядке. –  Jan 03 '19 at 17:10
  • @PavelMayorov, сейчас нормально стало, до этого ответ C#, 201 ставил на первое место – Андрей NOP Jan 03 '19 at 17:45
  • @Let'ssayPie потому что надо последнюю версию скрипта использовать, а не устаревшую :-) – Pavel Mayorov Jan 03 '19 at 19:15
  • @АндрейNOP я уж было подумал, что это из-за моей правки что-то сломалось, а вы про старую версию... Не пугайте так! – Pavel Mayorov Jan 03 '19 at 19:16
  • @PavelMayorov, ну как раз после правки я и смотрел – Андрей NOP Jan 03 '19 at 19:32
  • @АндрейNOP это странно... Там же стоит преобразование к числу, только что еще раз проверил. – Pavel Mayorov Jan 03 '19 at 19:49
  • @Let'ssayPie считается ли [][](массив массивов) и [,](двумерный массив) одним и тем же? – iluxa1810 Jan 09 '19 at 09:23
  • 1
    @Let'ssayPie касательно 'чем каждый язык способен посоревноваться?' Можно поставить все языки в одинаковые рамки, сказав, что можно пользоваться такими-то такими-то операторами, тем самым искусственно поставив все языки в одинаковые рамки. А то получается, что в одном языке прямо "из коробки" есть нужные функции и он может решить все одной строчкой. Например, хочешь решать через Reverse? Будь добр сам ее дополнительно реализовать и как следствии код между языки будет ~ одинаковым по размеру. – iluxa1810 Jan 09 '19 at 09:58
  • @Let'ssayPie и еще вопрос: а обязательно возвращать массив из функции? Например, в C# я могу вернуть IEnumerable, который вызывающая сторона одним движением руки может кастануть в массив. – iluxa1810 Jan 09 '19 at 13:36
  • @iluxa1810, изначально придумано так, чтобы возвращал массив, увы. –  Jan 09 '19 at 14:06
  • Забавно, как просьба "Если это неприемлемо, скажите" была молча проигнорирована... – Groxan Jan 12 '19 at 09:00
  • @Groxan, хотел уделить этому внимание позже, с телефона не очень удобно в дороге. Спасибо. –  Jan 12 '19 at 09:06

18 Answers18

15

Haskell, 39 40 42

r=reverse;s[]=[];s(h:t)=r h++s(map r t)

https://ideone.com/JYttmr

12

Python, 56

f=lambda l:sum([x[::i%2*2-1]for i,x in enumerate(l)],[])

Спасибо @АндрейNOP за подсказку!

Python, 60

f=lambda l:sum([[x[::-1],x][i&1]for i,x in enumerate(l)],[])

https://ideone.com/JPyzUQ (эта версия с лямбда функцией была любезно предоставлена @Let's say Pie)


Попытка 2: инвалидирована по причине неправильного оформления - решение должно быть реализовано как функция

Python, 49

sum([[x[::-1],x][i&1]for i,x in enumerate(l)],[])

https://ideone.com/WdHq4n

PS @КириллМалышев подсказал как можно сократить код еще на 6 символов - спасибо!!


Попытка 1:

Python, 55

sum([x if i&1 else x[::-1] for i,x in enumerate(l)],[])

https://ideone.com/2hoF3P

MaxU - stand with Ukraine
  • 149,321
  • 12
  • 59
  • 132
11

Python, 43

f=lambda m,a=-1:m and m.pop(0)[::a]+f(m,-a)

https://ideone.com/fQVgtD

10

Octave, 47

@(l,b=l(1:2:end,:)=fliplr(l(1:2:end,:)))l'(:)';

Try it online!

Если разрешить возвращать не вектор-строку, а вектор-столбец, сокращается на 1 символ:

Octave, 46

@(l,b=l(1:2:end,:)=fliplr(l(1:2:end,:)))l'(:);

Try it online!

Прошлый вариант без анонимной функции:

Octave, 40

l(1:2:end,:)=fliplr(l(1:2:end,:));l'(:)'

Try it online!

10

JavaScript, 38

Данный код работает в Firefox, но не работает на V8 (из-за специфичного алгоритма сортировки). Если это неприемлемо, скажите =)

f=a=>a.flatMap((x,i)=>x.sort(_=>~i&1))

console.log(f([[4,3,2,1],[5,6,7,8],[12,11,10,9],[13,14,15,16]]));


JavaScript, 40

f=a=>a.flatMap((x,i)=>i%2?x:x.reverse())

console.log(f([[4,3,2,1],[5,6,7,8],[12,11,10,9],[13,14,15,16]]));

Groxan
  • 1,554
  • Очень странно что с sort вообще работает – Андрей NOP Jan 04 '19 at 18:33
  • @АндрейNOP вроде ничего странного. sort принимает функцию-компаратор и возвращает отсортированный массив. Когда мы в компараторе на любой паре элементов возвращаем 1, он думает, что предыдущий элемент всегда больше следующего, и получается аналог reverse. А когда возвращаем 0, то ничего не сортируется. – Groxan Jan 04 '19 at 18:41
  • А, это компаратор, я думал что это функция-селектор, ок – Андрей NOP Jan 04 '19 at 18:53
  • С sort не везде работает, потому что stable sort никто не гарантирует. // сс @АндрейNOP – Qwertiy Jan 09 '19 at 09:15
  • @Qwertiy "Несмотря на кажущуюся необходимость, вытекающую из названия, устойчивость совсем не обязательна для правильности сортировки и чаще всего не соблюдается, так как для её обеспечения практически всегда необходимы дополнительная память и время." – Groxan Jan 09 '19 at 09:51
  • @Qwertiy, ну тут более того, дело даже не в стабильности, а в том, что алгоритм имеет право сравнить пару элементов несколько раз и один раз они могут идти в одном порядке, а другой — наоборот. По идее вообще в каких-то реализациях алгоритма сортировки такое может привести к зацикливанию – Андрей NOP Jan 09 '19 at 09:51
  • Проблема в том, что в V8 используется другой алгоритм сортировки - Timsort, который ломается, когда компаратор отдает константу – Groxan Jan 09 '19 at 10:05
  • 1
    Чёрт, да хорош уже! Надеюсь ваш вариант 38 символов не защитают! (шутка :)) – Андрей NOP Jan 09 '19 at 15:17
  • @АндрейNOP Хыхы, у меня блин из-за этого работа встала =) – Groxan Jan 09 '19 at 16:17
  • из-за специфичного алгоритма сортировки — зря вы это написали, стандарт как-то определяет какой алгоритм сортировки должен использоваться движком? А если у меня будет своя реализация JS и sort будет сортировать пузырьком, то ваш код зациклится :) – Андрей NOP Jan 11 '19 at 09:41
  • @АндрейNOP во-первых, как раз на пузырьке ничего не зациклится. Во-вторых, как-то не очень сравнивать "свою реализацию JS" с движком Mozilla. Firefox занимает достаточно большую долю на рынке, именно поэтому я считаю, что данный код имеет место быть. В-третьих, что значит "зря я это написал"? Я дал людям знание, что проблема не в каком-то баге, а в конкретном алгоритме сортировки (в том числе, чтобы избежать сообщений про "stable sort" и т.п.). Возможно вас задело слово "специфичный"? Так оно вовсе не означает "плохой". – Groxan Jan 11 '19 at 13:24
  • Ок, пузырек не зациклился, но зациклится сортировка вставками. Ну да ладно, я просто имею ввиду, что ваш компаратор возвращает одно и то же значение для пары (a, b) и для пары (b, a), что само по себе уже неоднозначность – Андрей NOP Jan 11 '19 at 14:15
9

JavaScript, 54

f=a=>a.reduce((c,n,i)=>c.concat(i%2?n:n.reverse()),[])

console.log(f([[4, 3, 2, 1], [5, 6, 7, 8], [12, 11, 10, 9], [13, 14, 15, 16]]));

9

Python, 62 61

Пока ничего лучше варианта с рекурсией не придумал :)

f=lambda m,x:m and(x&1and m.pop(0)or m.pop(0)[::-1])+f(m,x+1)

https://ideone.com/i2d0f6

8

F#, 68

let rec f=function|[]->[]|h::t->List.rev h@(t|>List.map List.rev|>f)

https://ideone.com/S6PhEZ

7

PowerShell, 51

$f={$args[0]|%{if(++$i%2){[Array]::Reverse($_)}$_}}

Try it online!

7

PHP, 93 91

function f($a){foreach($a as$v)$r[]=$_++&1?$v:array_reverse($v);return array_merge(...$r);}

https://ideone.com/XsiPap

7

C#, 62

dynamic s(int[][]a)=>a.SelectMany((x,i)=>i%2>0?x:x.Reverse());

https://repl.it/repls/EmbarrassedHalfCommand

Groxan
  • 1,554
  • судя с вопроса функция должна принимать двумерный массив!) – Yaroslav Jan 06 '19 at 20:08
  • Массив массивов - это надмножество двумерных массивов :) В нашем случае int[][] тоже можно назвать двумерным массивом. Мне кажется, в этом и прикол код гольфа - использовать разные трюки, чтобы сделать код короче :) – Groxan Jan 06 '19 at 22:23
  • @Yaroslav Кстати, кое-кто тоже вместо того, чтобы вернуть массив ("судя с вопроса"), вернул List. И стоит отметить, его за это никто не минусовал! ;) – Groxan Jan 06 '19 at 22:34
  • согласен ;) ) ) – Yaroslav Jan 06 '19 at 22:42
  • @Groxan, тем не менее, функция не примет на вход int[,] так как не сможет его неявно преобразовать => int[,] и int[][]- это 2 разных типа => на вход все таки нужно принимать int[,], а уже внутри, если вам удобно, кастовать в int[][]. Я бы уточнил у ТСа правила. – iluxa1810 Jan 09 '19 at 09:31
  • @iluxa1810, я думаю, что это непринципиально, потому что во многих языках вообще такого [,] нету, есть только [][] (да и вообще нет массивов в привычном понимании, есть только списки) – Андрей NOP Jan 09 '19 at 09:59
  • @АндрейNOP Ну это читерство=). Так как решение через [][] короче благодаря LINQ. – iluxa1810 Jan 09 '19 at 10:06
  • @iluxa1810, ну почему читерство? это допускается правилами, вы можете выбрать тот или иной вариант, который выгоднее вам. Цель всего этого — чисто развлекательная :) – Андрей NOP Jan 09 '19 at 10:12
6

PHP, 138 105

function f($a){foreach($a as$i=>$y){foreach($y as$x=>$w){$r[]=$i&1?$w:array_reverse($y)[$x];}}return $r;}

https://3v4l.org/DgDi8

vgedich
  • 93
  • 8
  • По сути это не является отдельной, новой функцией, и в результат должен получиться одномерный массив, а не двумерный. –  Jan 03 '19 at 13:14
  • @Let'ssayPie исправил – vgedich Jan 04 '19 at 08:23
  • 1
    кстати, можно не ставить пробел между return и переменной, допустимо return$r; –  Jan 05 '19 at 11:39
6

C#, 188 184

List<T> S<T>(T[,]a){var l=new List<T>();int m=a.GetLength(1);for(int i=0;i<m;i++){if((i+2)%2==0)for(int j=m-1;j>=0;j--)l.Add(a[i,j]);else for(int j=0;j<m;j++)l.Add(a[i,j]);}return l;}

Тест на deck.net

Yaroslav
  • 1,887
  • Вариант №2 не работает - он просто сортирует вход по возрастанию. Вот пример (изменены входные данные): https://deck.net/d4e69aa13bd2563a6bcb987de9658203 – Groxan Jan 09 '19 at 11:32
6

C#,171 168 163 153

Так как решения через LINQ уже были, то предлагаю вашему вниманию традиционных подход.

Минифицированная версия:

T[]F<T>(T[,]a){var d=a.GetUpperBound(1);var r=new List<T>();for(int i=0;i<=d;i++){var b=i%2>0;int j=b?0:d;while(j<=d&j>=0){r.Add(a[i,j]);j=b?++j:--j;}}return r.ToArray();}

Удобночитаемая:

    static T[] F<T>(T[,] a)
    {
        var d = a.GetUpperBound(1);
        var r = new List<T>();
        for (int i = 0; i <= d; i++)
        {
            var b = i % 2 > 0;
            int j = b ? 0 : d;
            while (j <= d & j >= 0)
            {
                r.Add(a[i, j]);
                j = b ? ++j : --j;//Трюк, что бы сэкономить символы на if/else
            }
        }
        return r.ToArray();
    }

Чуть чуть подправил:

T[]F<T>(T[,]a){var d=a.GetUpperBound(1);var r=new List<T>();for(int i=0;i<=d;i++){var b=i%2>0;int j=b?0:d;while(j<=d&j>=0){r.Add(a[i,b?j++:j--]);}}return r.ToArray();}

Удобночитаемая:

 T[] F<T>(T[,] a)
    {
        var d = a.GetUpperBound(1);
        var r = new List<T>();
        for (int i = 0; i <= d; i++)
        {
            var b = i % 2 > 0;
            int j = b ? 0 : d;
            while (j <= d & j >= 0)
            {
                r.Add(a[i, b ? j++ : j--]);
            }
        }
        return r.ToArray();
    }

Опять чуть подправил:

T[]F<T>(T[,]a){var d=a.GetLength(1)-1;var r=new List<T>();for(int i=0;i<=d;i++){var b=i%2>0;int j=b?0:d;while(j<=d&j>=0)r.Add(a[i,b?j++:j--]);}return r.ToArray();}

Удобночитаемая:

T[] F<T>(T[,] a)
{
    var d = a.GetLength(1) - 1;
    var r = new List<T>();
    for (int i = 0; i <= d; i++)
    {
        var b = i % 2 > 0;
        int j = b ? 0 : d;
        while (j <= d & j >= 0)
            r.Add(a[i, b ? j++ : j--]);
    }
    return r.ToArray();
}

И еще чуть-чуть убрал все лишнее:

T[]F<T>(T[,]a){int d=a.GetLength(1),g=0;var r=new T[d*d];for(int i=0;i<d;i++){var b=i%2>0;int j=b?0:d-1;while(j<d&j>=0)r[g++]=a[i,b?j++:j--];}return r;}

Удобночитаемый:

    T[] F<T>(T[,] a)
    {
        int d = a.GetLength(1), g = 0;
        var r = new T[d * d];
        for (int i = 0; i < d; i++)
        {
            var b = i % 2 > 0;
            int j = b ? 0 : d - 1;
            while (j < d & j >= 0)
                r[g++] = a[i, b ? j++ : j--];
        }
        return r;
    }
iluxa1810
  • 24,899
6

Perl 5, 81

sub f{foreach$row(@_){foreach$val(@$row){push@$s,$i++%2?@$val:reverse@$val;}}$s;}

Try it online!

5

Groovy, 42

f={i=0;it.each{it.reverse i=!i}.flatten()}

https://ideone.com/XirvAC

Nick
  • 2,468
4

C, 97

int f(int n,int a[n][n],int*b){for(int i=0;i<n;i++)for(int j=0,k=n;j<n;j++)*b++=a[i][i%2?j:--k];}

Проверить можно здесь: https://ideone.com/gkk7Di.

eanmos
  • 6,651
3

Ruby, 63

def f(a,x)a[0]?(x%2==0?a.shift.reverse: a.shift)+f(a,x+1):[]end

https://ideone.com/T0MECG