Зробіть тренажер для обертання міхура


23

Бульбашки - це розвага максимального рівня. Кожен може погодитися з цим.

Тепер ви змусите навіть комп’ютери насолоджуватися обгортанням бульбашок.

Технічні характеристики

Вам дадуть два цілі числа, w і h. (Кожне відповідає ширині і висоті)

Ваша програма повинна виводити всі w * h фази, що очікують 1 секунду між кожною з них, і закінчуватись.

Кожне обгортання міхура починається з усіх клітин.

Наприклад, обгортка міхура 4 * 6 починається так:

O_O_
_O_O
O_O_
_O_O
O_O_
_O_O

І на кожній фазі вискакується випадкова клітина, що не вискочила. Наприклад,

O_O_
_O_O
O_X_
_O_O
O_O_
_O_O

Програма повинна завершитися, коли всі комірки вискакують. ака.

X_X_
_X_X
X_X_
_X_X
X_X_
_X_X

Приклади

(4,6)
(5,5)
(6,2)
(10,10)
(7,9)

Чи можемо ми використовувати 1і 0замість Oі X?
Павло

1
NEEDZ BUBBLEZ, надішліть допомогу
Крістофер

3
Чи допустимо, щоб а (1,1)не містив бульбашок (наприклад, "ліворуч у верхній лівій частині" - це завжди підкреслення)?
Джонатан Аллан

1
@JonathanAllan Так.
Метью Ро Ро

1
@KevinCruijssen Це не обов'язково має бути повноцінною програмою.
Меттью Рох

Відповіді:


7

C (Windows), 260 248 байт

#import<windows.h>
i,j,l,r;b(w,h){char*s=malloc(l=w*h+h);for(i=h;i--;*s++=10)for(j=w;j--;*s++=i%2^j%2?79:45);*(s-1)=0;s-=l;for(srand(time(0));j>system("cls")+puts(s)-2;j>-1?s[j]=88:0)for(Sleep(1000),r=rand(),j=-2,i=r+l*2;--i-r;j=s[i%l]==79?i%l:j);}

введіть тут опис зображення


Зауважте, що функція сну в бібліотеці потоків, яка включена в C ++ 11.
Метью Ро Ро

@MatthewRoh Так, але це коротше, і system("cls")він також є специфічним для Windows, так що код також не буде більш портативним з бібліотекою потоків. І з C ++ мені також потрібно було б включити iostreamабо cstdio.
Steadybox

btw не потрібно скидати екран. це зробить її коротшою.
Метью Ро Ро

5

Пітон 3 , 222 220 байт

На це я вперше відповідаю, тому будьте ласкаві (і вкажіть на помилки, які я допустив).

import time,random as t
def f(c,r):
 p=print;a='0_'*c;d=((a[:c]+'\n'+a[1:c+1]+'\n')*r)[:-~c*r]
 for i in[1]*((r*c+r%2*c%2)//2):
  p(d);k=1
  while d[k]!='0':k=t.randrange(len(d))
  d=d[:k]+'X'+d[k+1:];time.sleep(1)
 p(d)

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

Як це працює:

  1. Ланцюг багато '0 _' разом
  2. Розбийте на частини '0_0 _... \ n' і '_0_0 ... \ n' і з'єднайте
  3. Генеруйте випадкові індекси, поки знак в індексі не дорівнює "0"
  4. Створіть нову рядок із знаком у генерованому індексі замінено символом "X" (Чорт забирає пітон для незмінних рядків!)
  5. r*c+r%2*c%2Часи повторень : r*cу шаблоні є бульбашки, якщо тільки r і c не є непарними, і в цьому випадку вони є r*c+1.

1
Ласкаво просимо до PPCG!
AdmBorkBork

1
Це досить незначно, але ваша ширина і висота зворотні. Хоча чудова відповідь! (Просто змініть його f(c,r)і ви будете добре).
rassar

@rassar Woops, дякую!
nile

4

MATL , 37 байт

:!i:+o`T&Xxt3:q'_OX'XEcD2y1=ft&v1Zr(T

У верхньому лівому куті завжди є підкреслення (дозволено викликом).

Екран очищається між фазами. Я міг би зберегти байт, не очищаючи екран, але це виглядає краще так.

Програма виходить із помилкою ( дозволено за замовчуванням ) після відображення всіх фаз.

Спробуйте в MATL Online! (Якщо це не спрацює через пару секунд, оновіть сторінку та повторіть спробу).


4

Математика (145 байт)

Анонімна функція, має висоту і ширину в якості вхідних даних (в такому порядку - якщо це проблема, замініть {##}з {#2,#}в середині коди для додаткового 2 байта).

Код:

Monitor[Do[Pause@1,{i,NestList[RandomChoice@StringReplaceList[#,"O"->"X"]&,""<>Riffle["_"["O"][[Mod[#+#2,2]]]&~Array~{##},"
"],Floor[##/2]]}],i]&

Пояснення:

  • ""<>Riffle[Array["_"["O"][[Mod[#+#2,2]]]&,{##}],"\n"] створює початкове, незапущене обгортання міхура, створюючи масив "_" s та "O" s, а потім StringJoining їх між новими рядками.
  • NestList[RandomChoice@StringReplaceList[#,"O"->"X"]&,..., Floor[##/2]]неодноразово вибирає один із "O", щоб замінити на "X" стільки разів, скільки є "O" s (що є Поверх [ширина * висота / 2] - завдяки @JonathanAllan за ідею поставити "_ "замість" O "у верхньому лівому куті, інакше це буде Ceilingзамість цього і, таким чином, на 2 байти більше).
  • Monitor[Do[Pause@1,{i,...}],i]змушує iприймати значення зі списку, який ми тільки що обчислили, протягом 1 секунди, і динамічно друкує i.

Приклад виводу:

GIF від Mathematica вискакуючи міхур-обгортку


3

Желе , 30 29 байт

=”OTX
+þ⁹++µị⁾_OYµṄœS1”XǦµÐL

Приклад виконання

Викликає посилання як діаду з програмними аргументами, а потім виходить із повідомленням (код для якого є çṛ“\'=ṙMḋḌẓ(ėo»)

Нюанс: нижня права "клітинка" завжди буде бульбашкою (а не верхньою лівою, як приклад у запитанні). Це потрібно для того, щоб при спливанні всіх бульбашок випадковий вибір повертав 0, який буде "X"в кінець списку - заміна якого потім не змінює значення і розбиває цикл.

Примітка: не очищає екран (не вказано, і я не знаю, як це зробити).

Як?

=”OTX - Link 1, choose a random O index or 0: string   e.g. "_O_\nX_O"
 ”O   - "O"
=     - equals (vectorises over the string)            e.g. [0,1,0,0,0,0,1]
   T  - truthy indexes                                 e.g. [2,7]
    X - random choice (if empty this returns 0)

+þ⁹++µị⁾_OYµṄœS1”XǦµÐL - Main link: w, h              e.g. 3, 2
                        - left argument (implicit), w  e.g. 3
  ⁹                     - right argument, h            e.g. 2
 þ                      - outer product with
+                       -     addition                 e.g. [[2,3,4],[3,4,5]]
                        - left argument (implicit), w  e.g. 3
   +                    - add                          e.g. [[5,6,7],[6,7,8]]
                        - right argument (implicit), h e.g. 2
    +                   - add                          e.g. [[7,8,9],[8,9,10]]
     µ                  - monadic chain separation
       ⁾_O              - "_O"
      ị                 - index into (1-based & mod)   e.g. [['_','O','_'],['O','_','O']]
                        -     note: the additions above assure the last entry is an 'O'.
          Y             - join with line feeds         e.g. ['_','O','_','\n','O','_','O']
           µ        µ   - monadic chain separations
                     ÐL - loop until the results are no longer unique:
            Ṅ           -     print with a trailing line feed and yield
             œS1        -     sleep for 1 second and yield
                   ¦    -     apply to index
                  Ç     -         given by calling the last link (1) as a monad 
                        -                 (a random O index or 0 if none exists)
                ”X      -         an "X"  (      ... which will be an X already)

@ ГригорийПерельман написав це.
Джонатан Аллан

2

Scala , 764 байт

object B{
  def main(a: Array[String]):Unit={
    val v=false
    val (m,l,k,r,n)=(()=>print("\033[H\033[2J\n"),a(0)toInt,a(1)toInt,scala.util.Random,print _)
    val e=Seq.fill(k, l)(v)
    m()
    (0 to (l*k)/2-(l*k+1)%2).foldLeft(e){(q,_)=>
      val a=q.zipWithIndex.map(r => r._1.zipWithIndex.filter(c=>
        if(((r._2 % 2) + c._2)%2==0)!c._1 else v)).zipWithIndex.filter(_._1.length > 0)
      val f=r.nextInt(a.length)
      val s=r.nextInt(a(f)._1.length)
      val i=(a(f)._2,a(f)._1(s)._2)
      Thread.sleep(1000)
      m()
      val b=q.updated(i._1, q(i._1).updated(i._2, !v))
      b.zipWithIndex.map{r=>
        r._1.zipWithIndex.map(c=>if(c._1)n("X")else if(((r._2 % 2)+c._2)%2==0)n("O")else n("_"))
        n("\n")
      }
      b
    }
  }
}

Як це працює

Алгоритм спочатку заповнює 2D послідовність помилковими значеннями. Він визначає, скільки ітерацій (відкритих полів) існує на підставі аргументів командного рядка, що містяться. Це створює складку з цим значенням як верхню межу. Ціле значення згину використовується лише неявно як спосіб підрахунку кількості ітерацій, за якими повинен працювати алгоритм. Заповнена нами послідовність заповнена послідовністю є початковою послідовністю для складання. Це використовується для генерування нової 2D послідовності помилкових значень із співвідповідними індексами.

Наприклад,

[[false, true],
 [true, false],
 [true, true]]

Буде перетворений на

[[(false, 0)], [(false, 1)]]

Зауважте, що всі списки, які є повністю правдивими (мають довжину 0), у списку результатів опущені. Потім алгоритм приймає цей список і вибирає випадковий список у найбільш віддаленому списку. Випадковий список обирається як довільний рядок, який ми вибираємо. З цього випадкового рядка ми знову знаходимо випадкове число, індекс стовпця. Як тільки ми знайдемо ці два випадкові індекси, ми спимо нитку, на якій ми знаходимося, протягом 1000 мілісекунд.

Після закінчення сну ми очищаємо екран і створюємо нову дошку зі trueзначенням, оновленим у створених нами випадкових індексах.

Щоб правильно роздрукувати це, ми використовуємо mapта поштовуємо його індексом карти, щоб це було в нашому контексті. Ми використовуємо значення істинності послідовності щодо того, чи слід надрукувати Xабо, або Oабо _. Щоб вибрати останнє, ми використовуємо значення індексу як наш путівник.

Цікаві речі, що слід зазначити

Щоб зрозуміти, чи повинен він друкувати Oабо _, використовується умовний ((r._2 % 2) + c._2) % 2 == 0. r._2посилається на індекс поточного рядка, тоді як c._2посилається на поточний стовпець. Якщо один із непарних рядків, r._2 % 2буде 1, тому зміщується c._2на одне в умовному. Це гарантує, що на непарних рядках стовпці переміщуються на 1 за призначенням.

"\033[H\033[2J\n"Друкуючи рядок , згідно з деякою прочитаною вами відповіді Stackoverflow очищає екран. Це писати байти в термінал і робити якісь прикольні речі, які я насправді не розумію. Але я знайшов, що це найпростіший спосіб зробити це. Однак він не працює на емуляторі консолі Intellij IDEA. Вам доведеться запустити його за допомогою звичайного терміналу.

Ще одне рівняння, яке може бути дивним, коли ми вперше подивимось на цей код (l * k) / 2 - (l * k + 1) % 2. Спочатку давайте демістифікуємо імена змінних. lстосується перших аргументів, переданих у програму, тоді як kстосується другого. Щоб перекласти його (first * second) / 2 - (first * second + 1) % 2,. Мета цього рівняння - придумати точну кількість ітерацій, необхідних для отримання послідовності всіх X. Перший раз, коли я це робив, я просто робив це, (first * second) / 2як це мало сенс. Для всіх nелементів у кожному списку є n / 2бульбашки, які ми можемо випустити. Однак ця помилка під час роботи з такими входами, як(11 13). Нам потрібно обчислити добуток двох чисел, зробити його непарним, якщо це парне, і навіть якщо це непарне, а потім взяти мод на 2. Це працює, тому що рядки та стовпці, що непарно, потребують меншої ітерації щоб дійти до кінцевого результату.

mapвикористовується замість forEachсимволу a, оскільки він містить менше символів.

Речі, які, ймовірно, можуть бути покращені

Одне, що насправді клопоче мене про це рішення, - це часте використання zipWithIndex. Це займає стільки символів. Я намагався зробити це так, щоб я міг визначити свою власну функцію з одним символом, яка просто виконувала бzipWithIndex зі значенням, яке передається. Але виявляється, що Scala не дозволяє анонімній функції мати параметри типу. Можливо, є ще один спосіб робити те, що я роблю, не використовуючи, zipWithIndexале я не надто замислювався над розумним способом зробити це.

В даний час код працює в два проходи. Перша створює нову плату, а друга пропускає її. Я думаю, що якби поєднати ці два проходи в один прохід, це дозволить заощадити пару байтів.

Це перший гольф з кодом, який я зробив, тому впевнений, що є багато можливостей для вдосконалення. Якщо ви хочете побачити код, перш ніж я максимально оптимізував для байтів, ось він.


1

JavaScript (ES6), 246 229 байт

document.write(`<pre id=o></pre>`)
setInterval(_=>{(a=o.innerHTML.split(/(O)/))[1]?a[Math.random()*~-a.length|1]=`X`:0;o.innerHTML=a.join``},1e3)
f=(w,h)=>o.innerHTML=[...Array(h)].map((_,i)=>`O_`.repeat(w+h).substr(i,w)).join`
`
<div oninput=f(+w.value,+h.value)><input id=w type=number min=1><input id=h type=number min=1>


Ширина була не в клітинках, але включала пробіли (підкреслення).
Метью Ро Ро

@MatthewRoh Вибачте, я згадав виправити його на висоту, але забув перевірити ширину.
Ніл

Хм .. не може ця частина: `${`_O`.repeat(w).slice(w)} ${`O_`.repeat(w).slice(w)}якось поєднуватися? Можливо, логічний_вираз прапор спочатку визначити , _Oчи O_, а потім зробити .repeat(w).slice(w)?
Кевін Кройсейсен

1
@KevinCruijssen Я втратив 16 байт через швидку помилку, яку в той час я не встиг пограти в гольф. З того часу я поглянув і придумав економію 17 байт,
Ніл,

1

Python - 290 байт

Я жодного разу раніше цього не робив - тому будь-яка конструктивна критика була б вдячна :)

Основна хитрість тут - просто прикро вкладені розуміння списку. Я міг би врятувати декількох персонажів, не маючи нового рядка між попами, але це просто виглядає некрасиво.

r=range
q=print
import random as n,time
def f(H,W):
    def p(b):
        q("\n".join(["".join(["O"if(i,j)in b else"X"if(i,j)in X else"_"for j in r(H)])for i in r(W)]));time.sleep(1);q()
    b=[(i,h)for h in r(H)for i in r(h%2,W,2)];n.shuffle(b);X=[]
    while len(b)>0:
        p(b);X+=[b.pop()]
    p(b)

Привіт, Ласкаво просимо до PPCG! Завдання полягало в тому, щоб прийняти wі hяк вхід (через STDIN, як функцію входу, або щось подібне), а не з жорстким кодом H=4 W=6. Крім того, хоча я ніколи не програмував на Python, я думаю, ви можете пограти в деякі місця у вашому поточному коді. Поради щодо гольфу в Python також можуть бути цікаві для ознайомлення, щоб дати вам ідеї щодо подальшого гольфу. Насолодитися перебуванням! :)
Кевін Круїссен

Також щодо Вашого коментаря: " Я міг би зберегти кілька символів, не маючи нового рядка між спливаючими вічками, але це просто виглядає некрасиво ". Незалежно від того, наскільки потворно чи як не зроблено це в програмах реального життя, codegolf збирається зберегти як якомога більше байтів. Чим коротше і негарніше, тим краще. ;)
Кевін Круїссен

@KevinCruijssen Python3 один над мною просто має функцію w, h, чи це дозволено?
Ар’я


1
Гаразд - зараз я зробив це функцією H і W.
Ар'я

1

Вугілля деревне , 49 46 39 байт (неконкурентне)

UONNO_¶_OAKAαA№αOβHWψβ«A§α§⌕AαO‽βXA№αOβ

Багатослівний

Oblong(InputNumber(), InputNumber(), "O_\n_O")
Assign(PeekAll(), a)
Assign(Count(a, "O"), b)
RefreshWhile (k, b) {
    AssignAtIndex(a, AtIndex(FindAll(a, "O"), Random(b)), "X")
    Assign(Count(a, "O"), b)
}

1

APL (Діалог) , 61 59 байт

⎕←m'O_'[2|-/¨⍳⎕]
(b/,m)[?+/b'O'=,m]←'X'
DL 1
2/⍨'O'∊⎕←m

⎕← вихід
m←m , де m є
'O_'[] ці символи, індексовані…
2| поділом-залишком, коли ділиться на два,
-/¨ різниці між кожною з
 усіх координат (індексів) у масиві
 числових входів форми (кількість рядків і стовпців )

(... )[... ]←'X' привласнити символ X одному з ...
b/ відфільтрований в кожному конкретному Ь (повинні бути визначені)
,m розпущеної елементи м, в зокрема , ...
? випадковий елемент (число букв) в діапазоні від одного до
+/ суми
b←Ь , де Ь є
'O'= булева бо там, де буква рівна
,mм, згорблена

⎕DL 1D e l ay одну секунду

→2 Перейдіть до рядка 2,
/⍨ якщо (засвідчено відфільтровано),
'O'∊ чи є буквою член
⎕←m виведеного значення, де виведене значення дорівнює m

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


Від версії 16.0 вона буде коротшою:

{0::→⋄'X'@(⊂(?∘≢⊃⊢)⍸'O'=⍵⊣⎕DL 1)⊢⎕←⍵}⍣≡'O_'[2|-/¨⍳⎕]


1

Пітон 3, 195 188 байт

import time,random
def f(w,h):
 a=bytearray(b'0-'*w*h);b=[*range(0,w*h,2)];random.shuffle(b);
 while 1:print(*(a.decode()[w*i:w*i+w]for i in range(h)),sep='\n');a[b.pop()]=88;time.sleep(1)

Використання bytearrayі, decodeздається, коротше, ніж нарізка та повторна збірка рядка a la a[:i]+'X'+a[i+1:].

import time,random
def f(w,h):
 x=[*range(1,h*w,2)];random.shuffle(x)
 while 1:
  for i in range(w*h):
   print('-X0'[(i%w%2!=i//w%2)+(i in x)],end='\n'[i%w<w-1:])
  print();time.sleep(1);x.pop()

0

Java 7, 317 байт

void c(int w,int h)throws Exception{String r="";int x=0,j=0,i;for(;j++<h;x^=1,r+="\n")for(i=0;i<w;r+=(i+++x)%2<1?"_":"O");for(System.out.println(r);r.contains("O");System.out.println(r=r.substring(0,x)+'X'+r.substring(x+1))){Thread.sleep(1000);for(x=0;r.charAt(x)!='O';x=new java.util.Random().nextInt(r.length()));}}

Пояснення:

void c(int w, int h) throws Exception{                     // Method with two integer parameters (throws Exception is required for the Thread.sleep)
  String r = "";                                           //  String we build to print
  int x=0, j=0, i;                                         //  Some temp values and indexes we use
  for(; j++<h;                                             //  Loop over the height 
      x^=1,                                                //    After every iteration change the flag `x` every iteration from 0 to 1, or vice-versa
      r += "\n")                                           //    And append the String with a new-line
    for(i=0; i<w;                                          //   Inner loop over the width
        r += (i++ + x)%2 < 1 ? "_" : "O")                  //    Append the String with either '_' or 'O' based on the row and flag-integer
    ;                                                      //   End inner width-loop (implicit / no body)
                                                           //  End height-loop (implicit / single-line body)
  for(                                                     //  Loop
    System.out.println(r);                                 //   Start by printing the starting wrap
    r.contains("O");                                       //   Continue loop as long as the String contains an 'O'
    System.out.println(r=                                  //   Print the changed String after every iteration
        r.substring(0,x)+'X'+r.substring(x+1))){           //    After we've replaced a random 'O' with 'X'
      Thread.sleep(1000);                                  //   Wait 1 second
      for(x=0; r.charAt(x) != 'O';                         //   Loop until we've found a random index containing still containing an 'O'
          x = new java.util.Random().nextInt(r.length()))  //    Select a random index in the String
      ;                                                    //   End loop that determines random index containing 'O' (implicit / no body)
  }                                                        //  End loop
}                                                          // End method

Тест gif (4,6)

введіть тут опис зображення


0

Perl, 148 байт

146 байт коду + -plпрапори.

$_=O x($x=$_+1);s/O\K./_/g;for$i(1..($y=<>)){$b.=($i%2?$_:_.s/.$//r).$/}}print$_="\e[H$b";while(/O/){$r=0|rand$y*$x+3;s/.{$r}\KO/X/s||redo;sleep 1

Щоб запустити його:

perl -ple '$_=O x($x=$_+1);s/O\K./_/g;for$i(1..($y=<>)){$b.=($i%2?$_:_.s/.$//r).$/}}print$_="\e[H$b";while(/O/){$r=0|rand$y*$x+3;s/.{$r}\KO/X/s||redo;sleep 1' <<< "6
4"

0

MATLAB (R2016b), 172 байти

Код:

x=input('');m=[eye(x(2),x(1)) ''];m(:)='O';m(1:2:end,2:2:end)='_';m(2:2:end,1:2:end)='_';o=find(m=='O');r=o(randperm(nnz(o)));disp(m);for i=r';pause(1);m(i)='X';disp(m);end

Рекомендації завжди вітаються! Спробуйте в Інтернеті!

Вихід програми:

введіть тут опис зображення

Пояснення:

x = input( '' );                    % Input
m = [ eye( x( 2 ), x( 1 ) ) '' ];   % Character Matrix
m( : ) = 'O';                       % Fill Matrix with "Bubbles"

m( 1:2:end, 2:2:end ) = '_';        % Alternate Spaces Between Bubbles (Part 1)
m( 2:2:end, 1:2:end ) = '_';        % Alternate Spaces Between Bubbles (Part 2)

o = find( m == 'O' );               % Index Bubble Locations
r = o( randperm( nnz( o ) ) );      % Randomize Bubble Locations

disp( m );                          % Display Initial Bubble Wrap Phase

for i = r'
    pause( 1 );                     % Pause for 1 Second
    m( i ) = 'X';                   % Pop Bubble
    disp( m );                      % Display Subsequent Bubble Wrap Phase
end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.