Код гольфу: Ваш власний горизонтальний змія ASCII


29

Дуже сильно натхненний цим викликом Code Golf: Ваша власна змія ASCII для домашніх улюбленців - я думав, що зробити її горизонтальною додасть додатковий шар складності.

Приклад горизонтальної змії:

            0 0               
  0        0 0 000            
00 0     00       000 0      0
    000 0            0 0   00 
       0                000   

А правила такі:

  1. Надруковано рівно 5 рядків символів
  2. Кожен рядок має рівно 30 символів, що складається з комбінації пробілів та символу, який ви вирішите намалювати змією
  3. Ваша змія починається на лінії 3
  4. Наступний рядок, який буде використаний для малювання змії, повинен бути вибраний випадковим чином із вашої поточної лінії, на одну лінію вгорі (якщо ви вже не на лінії 1) або на одну лінію внизу (якщо ви ще не на лінії 5).
    • Ці варіанти повинні бути однаково зваженими. Отже, якщо ви перебуваєте на лінії 1, у вас є 50% шансів залишитися на лінії 1 і 50% шансу перейти на лінію 2. Якщо ви перебуваєте на лінії 2, у вас є 33% шансів перейти на лінію 1, a 33% шансу залишитися на лінії 2 або 33% шансу перейти на лінію 3
  5. Вашій змії не потрібно відвідувати кожен рядок.

5
Ласкаво просимо до PPCG! Це хороший перший виклик.
Джузеппе

Для уточнення, якщо ми на краю, чи мусимо рівномірно підбирати (залишатися на одній лінії) та (переходити на іншу лінію) чи можемо мати неоднакові ваги?
Джузеппе

І від краю, чи мусимо ми рівномірно підбирати / вниз / ту ж лінію?
Джузеппе

2
Ммм ... принаймні 5-рядкове обмеження не дозволяє людям красти відповіді з другого із доданим транспонтом.
Чарівний восьминога Урна

9
Фізичне обертання монітора на 90 ° вважається байтом? : D
Ерік Дюмініл

Відповіді:


11

JavaScript (ES6), 98 байт

Збережено 7 байт завдяки @KevinCruijssen

Повертає масив з 5 рядків.

f=(y=2,a=[...'  0  '])=>a[0][29]?a:f(y+=(Math.random()*(y%4?3:2)|0)-!!y,a.map((v,i)=>v+=i-y&&' '))

Спробуйте в Інтернеті!

Прокоментував

f = (                       // given:
  y = 2,                    //   y = current line (0-indexed)
  a = [...'  0  ']          //   a[] = array of 5 lines
) =>                        //
  a[0][29] ?                // if all columns have been processed:
    a                       //   stop recursion and return a[]
  :                         // else:
    f(                      //   do a recursive call with:
      y += (                //     the updated value of y, to which we add -1, 0 or 1:
        Math.random() *     //       pick a random value in [0,1)
        (y % 4 ?            //         if y is neither 0 or 4:
          3                 //             multiply it by 3
        :                   //           else:
          2                 //             multiply it by 2
        ) | 0               //       force an integer value
      ) - !!y,              //     subtract either 0 or 1
      a.map((v, i) =>       //     for each value v at position i in a[]:
        v += i - y && ' '   //       append either '0' if i = y or a space otherwise
      )                     //     end of map()
    )                       //   end of recursive call

Ви можете скидати dта використовувати ((y%4?3:2)|0)-(y>0)для -6 ​​байт. Спробуйте в Інтернеті.
Кевін Кройсейсен

Корекція: -7 байт. 1В new Random(...)мається на увазі за замовчуванням, звичайно .. Спробуйте його в Інтернеті.
Кевін Кройсейсен

@KevinCruijssen Дякую! ( !!yзамість того, щоб (y>0)заощадити ще 2 байти.)
Арнольд

7

Вугілля деревне , 28 байт

P|   F³⁰«0≡ⅉ²M‽²↑±²M‽²↓M⊖‽³↓

Спробуйте в Інтернеті! Посилання на багатослівну версію коду. Пояснення:

P|   

Роздрукуйте трохи накладки, щоб примусити 5 рядків вивести.

F³⁰«

Повторіть 30 разів.

0

Роздрукуйте нуль (і рухайтеся горизонтально).

≡ⅉ²M‽²↑

Якщо координата Y дорівнює 2, рухайтеся вгору випадковим чином на 0 або 1.

±²M‽²↓

Якщо це -2, рухайтеся вниз випадковим чином на 0 або 1.

M⊖‽³↓

В іншому випадку рухайтеся вниз випадковим чином на -1, 0 або 1.


6

Perl, 68 байт

perl -E '$%=2;s:$:$n++%5-$%&&$":emg,$%-=!!$%+rand!($%%4)-3for($_=$/x4)x30;say'

Це зовсім не відчуває себе оптимальним.


5

Желе , 24 байти

3µ’o1r‘«5¥$Xµ30СṬ€o⁶z⁶Y

Спробуйте в Інтернеті!

Пояснення

3µ'o1r '«5 ¥ $ Xµ30СṬ € o⁶z⁶Y || Повна програма Niladic.
                         ||
3 || Починаючи з 3 ...
 µ µ30 || ... Виконати 30 разів ...
               С || ... І збирайте результати в список.
  'o1r' «5 ¥ $ X || - | Функція "Помічник" Монадіка.
  'o1 || - | Поточне ціле число, зменшене АБО 1.
     r X || - | Візьміть випадковий предмет у діапазоні від ^ до ...
      '«5 || - | ... Кількість збільшена, обмежена до 5 (використовує максимум).
         ¥ $ || - | Синтаксичні елементи. Використовується для групування посилань.
                 Ṭ € || Неправда кожна.
                   o⁶ || Логічний АБО з єдиним пробілом.
                     z⁶ || Транспортуйте з пробілами.
                       Y || Приєднуйтесь за новими лініями.


5

Пітон 3, 144 байти

@Ruts, @Turksarama і @mypetlion були дуже корисними для зменшення байтів

import random
m=[list(' '*30)for y in range(5)]
l=2
for i in range(1,30):
 m[l][i]=0
 l+=random.randint(~-(l<1),l<4)
for j in m:
  print(*j)

Постараюсь покращити це. Веселий виклик!


3
Змініть, l+=random.randint(-1,1) l=0 if l<0 else l l=4 if l>4 else lщоб l+=random.randint(~-(l<1),l<4)зберегти 31 байт.
mypetlion

1
Ви повинні мати можливість видалити багато пробілів та нових рядків.
Містер Xcoder

1
Змініть, m=[[' 'for x in R(w)]for y in R(h)]щоб m=[list(' '*w)for y in R(h)]зберегти 7 байт.
mypetlion

2
У python, booleanпідклас int. Так Falseможна використовувати замість 0і Trueможе замінити 1. ~Є унарний оператор побітового notі -оператор перевертає знак (помножити на -1). Так ~-(False)оцінює до -1та ~-(True)оцінює до 0.
mypetlion

1
Призначте свої початкові 0 у циклі та встановіть l після призначення. Це заощаджує вам один цілий рядок ( m[2][0]=0немає) та 2 байти на циклі for ( for i in R(1,30):стає for i in R(30):). Вам також потрібно буде перерахувати l після встановлення 0. Це призведе до 144 байт.
Турксарама

4

R , 120 114 байт

m=matrix
r=m(" ",30,5)
x=3
for(i in 1:30){r[i,x]=0;x=x+sample(-1:1,1,,m(c(0,rep(1,13)),3)[,x])}
write(r,"",30,,"")

Дякуємо @Giuseppe за додаткові 6 байт!

Використовується таблиця ймовірностей так:

> matrix(c(0,rep(1,13)),3)
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    1    1    1    1
[2,]    1    1    1    1    1
[3,]    1    1    1    1    0
Warning message:
In m(c(0, rep(1, 13)), 3) :
  data length [14] is not a sub-multiple or multiple of the number of rows [3]

де кожному стовпцю відповідає випадок, тобто колонка 1 вибирається, якщо змія знаходиться в рядку 1, що дає ймовірність 0, 1/2 та 1/2 вибрати відповідно -1 [спуститися], 0 [залишитися нерухомо] та 1 [ йти вгору] ( sampleавтоматично нормалізувати ймовірності до 1), стовпець 2 для рядка 2 дає ймовірності 1/3, 1/3 та 1/3 тощо тощо.

Спробуйте в Інтернеті!



@Giuseppe Дякую! Дійсно було це не було, і я забув використати переробку вектора для додаткових 0.
plannapus

3

SOGL V0.12 , 22 21 байт

3ā'∑∫⁵╗ž⁴H1ΧGI5χ⁴-ψ+;

Спробуйте тут!

Пояснення:

3                      push 3
 ā                     push an empty array - the canvas
  '∑∫                  30 times do, pushing counter            | stack = 3, [], 1
     ⁵                   duplicate the Y coordinate            | stack = 3, [], 1, 3
      ╗ž                 at those coordinates insert "+"       | stack = 3, ["","","+"]
        ⁴                duplicate from below                  | stack = 3, ["","","+"], 3
         H               decrease                              | stack = 3, [...], 2
          1Χ             maximum of that and 1                 | stack = 3, [...], 2
            G            get the item 3rd from top             | stack = [...], 2, 3
             I           increase it                           | stack = [...], 2, 4
              5χ         minimum of that and 5                 | stack = [...], 2, 4
                ⁴-       subtract from the larger a copy of the smaller value | stack = [...], 2, 2
                  ψ      random number from 0 to pop inclusive | stack = [...], 2, 2
                   +     add those                             | stack = [...], 4
                    ;    and get the array back ontop          | stack = 4, ["","","+"]

                         implicitly output the top item - the array, joined on newlines






2

SmileBASIC, 107 105 103 89 байт

FOR I=0TO 29FOR J=0TO 5LOCATE I,J?" 0"[Y+2==J]NEXT
Y=Y+RND(3)-1D=Y/3>>0Y=Y-D-D*RND(2)NEXT
NEXT

Ця відповідь цікавіша за вертикальну через (буквальні) крайні випадки.

64 байти, без пробілів:

FOR I=0TO 29LOCATE,Y+2?0;
Y=Y+RND(3)-1D=Y/3>>0Y=Y-D-D*RND(2)NEXT

Я також знайшов кілька варіантів рядка 2 однакової довжини:

Y=Y+RND(3)-1D=Y/3>>0Y=Y-D-D*RND(2)NEXT
Y=Y+RND(3)-1D%=Y/3Y=Y-D%-D%*RND(2)NEXT
Y=Y+RND(3)-1Y=Y-Y DIV 3*(RND(2)+1)NEXT
Y=Y+RND(3)-1Y=Y/3OR.Y=Y-D-D*RND(2)NEXT

Ціле ділення Y / 3 використовується для перевірки, чи є Y поза допустимого діапазону, а також для отримання знаку.


2

Java 8, 177 170 байт

v->{int a[][]=new int[5][30],c=0,r=2;for(;c<30;r+=Math.random()*(r%4>0?3:2)-(r>0?1:0))a[r][c++]=1;String R="";for(int[]y:a){for(int x:y)R+=x<1?" ":"~";R+="\n";}return R;}

-7 байт завдяки @ OlivierGrégoire .

Пояснення:

Спробуйте в Інтернеті.

v->{                // Method with empty unused parameter and String return-type
  int a[][]=new int[5][30],
                    //  Integer-matrix of size 5x30
      c=0,          //  Column, starting at index 0
      r=2;          //  Row, starting at index 2
  for(;c<30;        //  Loop `c` 30 times
      r+=Math.random()*(r%4>0?3:2)-(r>0?1:0))
                    //    After every iteration: change `r` with -1,0,1 randomly
                    //     If `r` is 0: random [0;2)-0 → 0,1
                    //     If `r` is 4: random [0;2)-1 → -1,0
                    //     If `r` is 1,2,3: random [0:3)-1 → -1,0,1
    a[r][c++]=1;    //   Fill the cell at indices `r,c` from 0 to 1
  String R="";      //  Result-String, starting empty
  for(int[]y:a){    //  Loop over the rows of the matrix
    for(int x:y)    //   Inner loop over the individual column-cells of the matrix
      R+=x<1?       //    If the value of the cell is still 0:
          " "       //     Append a space
         :          //    Else (it's 1):
          "~";      //     Append the character
    R+="\n";}       //   After every row, Append a new-line
  return R;}        //  Return the result-String

1
r+=Math.random()*(r%4>0?3:2)-(r>0?1:0)щоб зберегти кілька байт.
Олів’є Грегоар

@ OlivierGrégoire Я думав, що це вже зробив, але, мабуть, ні. Можливо, я це зробив нещодавно в іншій відповіді ..: S Спасибі!
Кевін Кройсейсен


1

Python 3 , 123 байти

from random import*
i,*a=2,
exec("a+=i,;i+=randint(-(i>0),i<4);"*30)
for x in range(5):print(''.join(' 0'[x==i]for i in a))

Спробуйте в Інтернеті!

Створіть масив цілих чисел, а потім перетворіть їх у кожен рядок.

Python 2 , 120 байт

from random import*
i=2;a=[]
exec"a+=i,;i+=randint(-(i>0),i<4);"*30
for x in range(5):print''.join(' 0'[x==i]for i in a)

Спробуйте в Інтернеті!

Для Py2 зайві паролі для execі printможуть бути видалені, але синтаксис у другому рядку недійсний.

Випереджаючи як подання Py2 за допомогою Rod, так і Py3 подання лінійним способом .


1

Рубі , 98 77 байт

->{a=(0..4).map{" "*30}
x=2
30.times{|i|a[x][i]=?@
x+=rand(3-17[x])-30[x]}
a}

Спробуйте в Інтернеті!

Лямбда, що повертає масив струн.

Моїм початковим імпульсом було генерувати стовпці та переміщувати їх, але набагато простіше просто уникнути цього кроку.

Я хотів би ініціювати aз [" "*30]*5, але це було б зробити неглибокі копії рядків, що призводить до дуже жирної, без slithery змії.

Я міг би використовувати такий констант, як Dприріст (за той самий підрахунок байтів), але Рубі скаржився б кожного разу, коли я призначив його. Я вирішив, що віддаю перевагу зменшенню читабельності, повторно використовуючи iсередину циклу, ніж купу попереджень про налагодження, які слід ігнорувати.

Я також хотів би зберегти кілька байтів за допомогою loop{x+=rand(3)-1;(0..4)===x&&break}, але це спричинило б упередженість по краях: 1/3 шанс повернути назад всередину, 1/3 шанс залишитися і 1/3 шанс вийти за межі деякий час, перш ніж врешті-решт ходити навмання (тобто "залишитися").

-20 байт: Використовуйте Ruby, Integer#[]щоб створити крихітні умови, забезпечуючи правильне зважування руху для всіх 5 позицій. Це замінює схему розриву циклу (з ненульовим шансом не змогти зупинитись) для величезної економії. Дякую, Еріку Думінілу !

-1 байт: Initialize aз (0..4).mapзамість 5.times, знову ж завдяки Ерік Duminil .

->{
  a = (0..4).map{ " " * 30 }      # a is the return array: 5 strings of 30 spaces
  x = 2                           # x is the snake position
  30.times{ |i|                   # For i from 0 to 29
    a[x][i] = ?@                  #   The ith position of the xth row is modified
    x += rand(3 - 17[x]) - 30[x]  #   Using bit logic, add rand(2 or 3) - (0 or 1)
  }
  a                               # Return the array of strings
}

Приємний старт. Немає потреби у внутрішній loop. Ви можете розрахувати приріст за допомогою rand(2+14[x])-30[x]або rand -(30[x])..15[x]. Мабуть, існує коротша версія. І все-таки -20 байт непогано! Спробуйте в Інтернеті!
Ерік Думініл

На 1 байт менше с x,a=2,(0..4).map{" "*30}. Спробуйте в Інтернеті!
Ерік Думініл

1
Нічого собі, 30[x]це чудова хитрість! Спасибі!
benj2240

1

Perl 6 , 85 байт

.join.say for [Z] ((' ',' ',0,' ',' '),{.rotate(set(0,+?.[0],-?.[4]).pick)}...*)[^30]

Спробуйте в Інтернеті!

Вираз з довгими дужками - це ледача послідовність, сформована з початкового елемента (' ', ' ', 0, ' ', ' '), першої вертикальної смуги виводу. Кожна послідовна смужка / список формується з попереднього шляхом виклику її rotateметоду, при цьому зсув вибирається випадковим чином з набору, що містить 0, 1(якщо перший елемент ненульовий), та -1(якщо п’ятий елемент ненульовий).

Матриця горизонтальних смуг транспозирується разом із [Z]оператором, перетворюючи її у список вертикальних смуг, кожну з яких потім joinвиводять у єдиний рядок та виводять за допомогою say.


1

Скала, 207 байт

val b=Array.fill(150)('.')
def s(y:Int,x:Int)={val r=Random.nextInt(6)
val z=y+(if(y>3)-r%2
else if(y<1)r%2
else r/2-1)
b(z*30+x)='$'
z}
(3/:(0 to 28))(s(_,_))
b.mkString("").sliding(30,30).foreach(println)

зразок:

...................$$$...$.$$.
.$$$..............$...$.$.$...
$...$$$..$...$$.$$.....$......
.......$$.$.$..$..............
...........$..................

знежирений:

val buf = List.fill(150)('.').toBuffer
def setRowCol (y:Int, x:Int): Int = {
  val r = Random.nextInt(6)
  val z = y + (
    if (y>3) 
        -(r%2)
    else if (y<1) 
        (r%2)
    else 
        r/2-1
  )
  buf (z * 30 + x) = '$'
  z
}
(3 /: (0 to 28)(setRowCol (_, _))
println 
buf.mkString ("").sliding(30,30).foreach(println)

Моє унікальне винахід - ну, я не читав інших рішень досі, це створити Random (6), який неявно два Randoms, (2 * 3). Якщо вдалині від кордону, я використовую значення r / 2 (0,1,2) і → (-1,0,1), підкажіть, щоб рухатися вгору або вниз. Якщо на кордоні, я можу уникнути дорогого виклику персонажа іншого випадкового виклику і просто взяти модуль (2), щоб вирішити, чи варто залишатись чи мені їхати.

Давайте подивимося на інші рішення. :)


Так, неправильне зображення зразка. Це робить. :)
користувач невідомий

скала скелі! ой .. код гольфу .. неправильне використання випадку воно з'являється .. Як, до біса, це потрапило java?
javadba

@javadba: Ви натиснули try itпосилання? Кевін Круїссен не містив котла, необхідного для складання цього коду або для його запуску в JShell, але я думаю, це відповідно до вказівок - може бути мета дискусія. Якщо вам подобається, ви можете спробувати зменшити цей код, скориставшись також двоматомним масивом. Друга ідея полягає в тому, щоб зменшити ковзаючий код в кінці. Деякий метод карти? Println прихований Кевіном. - Так, Array дає покращення на 8.
користувач невідомий

Нехай масштабує висновок про тип повернення int: збережено ще 4 символи.
користувач невідомий

так що зараз потрапляє в
бальний

1

Perl, 83 101 байт

perl -E '$l=3;map{map$s[$_-1].=/$l/?0:" ",1..5;$l-=1-int 3*rand;$l=~y/60/51/}1..30;say for@s'

Нове: Без імовірності питання на кордонах:

perl -E '$l=3;map{map$s[$_-1].=/$l/?0:" ",1..5;$l=int($l<2?1+2*rand:$l>4?6-2*rand:$l-1+3*rand)}1..30;say for@s'

Безголовки:

$l=3;                             #start line
map{
  map $s[$_-1].=/$l/?0:" ",1..5;  #0 at current char and line, space elsewhere
  $l-=1-int 3*rand;               #up, down or stay
  $l=int( $l<2 ? 1+2*rand
        : $l>4 ? 6-2*rand
        :        $l-1+3*rand )    #border patrol
}
1..30;                            #position
say for@s                         #output result strings/lines in @s

2
Ваш прикордонний патруль не дає правильної ймовірності 50% для перебування на краю.
Тон Євангелія

0

PowerShell , 133 байт

$a=(,' '*30),(,' '*30),(,' '*30),(,' '*30),(,' '*30);$l=2;0..29|%{$a[$l][$_]=0;$l+=0,(1,($x=1,-1),$x,$x,-1)[$l]|Random};$a|%{-join$_}

Спробуйте в Інтернеті!

Побудує двовимірний масив із 30 просторів у ширину на 5 ліній заввишки. (Примітка. Якщо хтось може придумати кращий ефективний спосіб ініціалізувати цей масив, я <3 вас назавжди.) Встановлює змінну помічника $lна 2(це використовується для того, на якому рядку був попередній сегмент змії). Потім петлі від 0до 29.

Кожну ітерацію ми встановлюємо своїм елементом змії 0. Тоді ми індексуємо складний масив із тим, Get-Randomщо вибираємо, чи піднімаємось ми вгору чи вниз чи залишаємось однаковими. Це додано назад $l.

Нарешті, ми пров'язуємо п'ять елементів $aта -joinїх внутрішні елементи в один рядок кожен. Ці п’ять рядків залишаються на конвеєрі, і неявна Write-Outputдає нам нові рядки безкоштовно.


0

Clojure, 123 байти

Ось приходять парени:

(let[l(take 30(iterate #(max(min(+(-(rand-int 3)1)%)4)0)3))](doseq[y(range 5)](doseq[x l](print(if(= y x)0" ")))(println)))

Безгольова версія:

(let [l (take
       30
       (iterate
        #(max
          (min
           (+ (- (rand-int 3) 1) %)
           4)
          0)
        3))]
(doseq [y (range 5)]
  (doseq [x l]
    (print (if (= y x) 0 " ")))
  (println)))

Створює список різної висоти тіла змії, а потім ітерає від 0 до 4. Щоразу, коли висота відповідає поточному рядку, вона надрукує 0, інакше порожній. Не дозволяти висотам перевищувати межу дійсно коштує байтів. Розпізнавання того, коли новий рядок в порядку, є більш інтенсивним, як і належить. Можна було легко написати сингл doseq, зробивши декартовий твір з x і y, але тоді не відомо, коли надрукувати новий рядок.


0

Python3 + numpy, 137 132 байти

Не найкоротший подання пітона, не найдовший і, безумовно, не найшвидший.

from pylab import*
j=r_[2,:29]
while any(abs(diff(j))>1):j[1:]=randint(0,5,29)
for i in r_[:5]:print(''.join(' #'[c] for c in j==i))

оновлення За допомогою numpyкоманди diff збережено 5 байт для тестування, чи змія є дійсною схемою, порівняно з обчисленням різниці вручну j[1:]-j[:-1].



0

R , 95 байт

x=3;l=1:5
write(t(replicate(30,{y=ifelse(x-l,' ',0);x<<-sample(l[abs(x-l)<2],1);y})),'',30,,'')

Наступний рядок xзавжди вибирається з рядків, які знаходяться на відстані не більше 1 від поточного рядка ( l[abs(x-l)<2]). Використання replicateзамість forциклу зберігає деякі байти, необхідні для ініціалізації матриці та маніпулювання, і вимагає використання <<-оператора при призначенні глобальної змінної x.

Спробуйте в Інтернеті!


0

05AB1E , 25 байт

Y30F©ð5×0®ǝs<DÌŸ4ÝÃΩ}\)ζ»

Спробуйте в Інтернеті!

Пояснення

Y                           # push the initial value 2
 30F                        # 30 times do
    ©                       # store a copy of the current value in register
     ð5×                    # push 5 spaces: "     "
        0®ǝ                 # insert 0 at the position of the current value
           s<DÌŸ            # push the range [current-1 ... current-1+2]
                4ÝÃ         # keep only numbers in [0 ... 4]
                    Ω       # pick one at random
                     }\     # end loop and discard the final value
                       )ζ   # transpose the list
                         »  # join by newlines
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.