Wygeneruj łańcuch boiska baseballowego

11

Cel

Napisz program lub funkcję, która przyjmuje dodatnią liczbę całkowitą ni losowo generuje prawidłową serię podziałek (odtąd zwaną łańcuchem podziałki) o długości n.

Wejście

Niezerowa, dodatnia liczba całkowita n<= 100

Wynik

Zwraca losowy ciąg znaków lub listę znaków, które reprezentują możliwy, prawidłowy ciąg długości tonu n. Użyte postacie to:

  • B - Piłka. Jeśli zgromadzisz 4 z nich, pałkarz idzie i kończy mrugnięcie.
  • S - Uderzenie. Jeśli zgromadzisz 3 z nich, ciasto się skończy i zakończy mruganie.
  • F - Faul. Zwiększy również liczbę uderzeń, ale nie może wydobyć pałkarza. To znaczy, że faul nie może być ostatnim rzutem w prawidłowym ciągu. Jakiekolwiek faule po dwóch uderzeniach / faulach nie zwiększą liczby uderzeń (pałkarz ma już w tym momencie 2 uderzenia, a 3 go wydostanie).
  • H - Hit. Pałkarz uderzył piłkę w grę i zakończył mrugnięcie.

(Jest to nieco uproszczone, ale nie martw się o to)

Prawidłowe ciągi znaków to te, które kończą się przekreśleniem, spacerem lub trafieniem.

Tzn. Niepoprawny ciąg znaków ma albo

  • dodatkowe boiska po 4. piłce, 3. uderzeniu lub trafieniu
  • zakończone przed wygenerowaniem czwartej piłki, trzeciego strajku lub trafienia.

Zasady

  • Twój program musi być w stanie wygenerować wszystkie możliwe wyniki dla danych wejściowych.
  • Twój program nie musi być jednakowo losowy, ale nadal musi być zgodny z poprzednią regułą.
  • To jest .

Przykłady

Input => Possible Outputs
1 => [H] #Can only end with a hit
2 => [S,H], [B,H], [F,H] #Can only end with a hit
3 => [S,S,S], [F,F,S], [B,B,H], ... #Can now strike-out, otherwise must end with a hit
4 => [B,B,B,B], [S,B,S,S], [B,F,S,S], [B,B,B,H], ... #Can now be walked, struck-out, or get a hit
6 => [S,B,S,B,B,H], [F,F,F,F,F,S], ... #Can now have a full-count (3 balls, 2 strikes) before finishing 

Input => Invalid Outputs
1 => [S], [B]    #Not enough for a strike-out/walk
2 => [S,S]       #Not enough for a strike-out/walk
2 => [H,H]       #Batter has already scored a hit
3 => [S,S,F]     #Fouls will not cause a strike-out
4 => [S,S,S,H]   #Batter has already struck out
5 => [B,B,B,B,B] #Batter has already walked
Veskah
źródło
1
Więc musimy być w stanie wyprodukować od 1 do nieskończoności F?
Quintec
Ciąg będzie miał maksymalnie 100 znaków. Faule są tym, co pozwala na tak długie struny do FS
rzucania
Och,
rozumiem
@Quintec Przeredagował to, by było trochę bardziej wyraźne na wszelki wypadek
Veskah

Odpowiedzi:

4

Python 2 , 128 bajtów

from random import*
def g(n):
 x=i=S=0;r=''
 while(S>2)+x<3>=i-S:x=randint(0,3);r+='BFSH'[x];S+=x>0;i+=1
 return(i==n)*r or g(n)

Wypróbuj online!

Losowo generuj łańcuch pitch, aż ciasto się skończy, wyślij go, jeśli okaże się, że ma odpowiednią długość, a w przeciwnym razie spróbuj ponownie od początku.


Python 2 , 136 bajtów

from random import*
def g(n):
 B=H=F=S=0;r=''
 while(F+S<3or'S'>x)>B/4+H:x=choice('BHFS');r+=x;exec x+"+=1"
 return(len(r)==n)*r or g(n)

Wypróbuj online!

xnor
źródło
Port Kevina sprawił, że zdałem sobie sprawę z tego, że rozkłada się na wyższe liczby. n=8może wygenerować łańcuch Fs na końcu
Veskah
2
@Veskah Nice catch. Nie liczyłem się z liczbą uderzeń (licząc faule), która może wzrosnąć do 6 i zmienić się, S/3żeby (S>2)to naprawić.
xnor
4

05AB1E ,  44  50 44 bajtów

Przekreślony nie &nbsp;44&nbsp;jest już 44 :)

[õ0U.µ["BFSH"3ÝΩ©è«®ĀX+U¼X2›®+3@¾X-3›~#}I¾Q#

Port odpowiedzi @xnor na Python 2 , więc upewnij się, że go również głosujesz, jeśli podoba ci się ta odpowiedź!
+6 bajtów z powodu poprawki błędu, a potem -6 bajtów ponownie dzięki @xnor , przenosząc jego znacznie bardziej wydajną poprawkę w porównaniu do mojej tymczasowej obejścia, jak się spodziewałem. ;)

Wypróbuj online lub sprawdź więcej losowych wyników .

Wyjaśnienie:

[                # Start an infinite loop:
 õ               #  (Re)set the result-string to an empty string ""
 0U              #  (Re)set variable `X` to 0
               #  Reset the counter_variable to 0
   [             #  Start an inner infinite loop:
    "BFSH"       #   Push string "BFSH"
          3ÝΩ    #   Push a random integer in the range [0,3]
             ©   #   Store this random integer in variable `r` (without popping)
              è  #   Index it into the string "BFSH"
               « #   Append it to the result-string
    ®Ā           #   If `r` is NOT 0:
      X+U        #    Increase `X` by 1
    ¼            #   Increase the counter_variable by 1
    X2›®+        #   Calculate `X`>2 (1 if truthy; 0 if falsey) + `r`
         3@      #   Check if this is larger than or equal to 3
    ¾X-          #   Calculate counter_variable - `X`
       3        #   Check if this is larger than 3
    ~            #   If either of the two checks above is truhy:
     #           #    Stop the inner infinite loop
   }             #  After the inner infinite loop:
    I¾Q          #  If the input and counter_variable are equal:
       #         #   Stop the outer infinite loop
                 # (and output the result-string at the top of the stack implicitly)
Kevin Cruijssen
źródło
1
@Veskah Na razie dokonałem prostej naprawy. Mam wrażenie, że xnor jest w stanie dokonać krótszej poprawki, więc prawdopodobnie przeniesie tę poprawkę, aby później zaoszczędzić trochę bajtów. :)
Kevin Cruijssen
1
Możesz to naprawić tak jak ja, zmieniając X/3na X>2.
xnor
@xnor Dzięki, wróć ponownie do 44 bajtów. Wiedziałem, że znajdziesz coś krótszego. ; p
Kevin Cruijssen
3

R , 148 bajtów

function(n){`~`=paste0
`*`=sample
o=""
while(nchar(o)<n-1){a=c("B"[T<4],"F","S"[F<2])*1
F=F+(a>"E")
T=T+(a<"F")
o=o~a}
o~c("B"[T>3],"H","S"[F>1])*1}

Wypróbuj online!

Generuje ciąg przy użyciu warunkowego włączenia do zbiorów danych próbkowania, aby upewnić się, że wynikiem jest możliwa sekwencja skoku.

Możliwe, że próbkowanie przy odrzucaniu (jak robi odpowiedź python xnora ) jest krótsze.

function(n){`~`=paste0		# alias
`*`=sample			# alias
o=""				# empty string for output
while(nchar(o)<n-1){		# do n-1 times:
a=c("B"[T<4],"F","S"[F<2])*1	# sample 1 from the string "BFS", conditionally including B or S if the ball/strike count is 3/2	
F=F+(a>"E")			# increment F (strike count) if sampled character is F or S
T=T+(a<"F")			# increment T (ball count) if sampled character is B
o=o~a}				# append a to output

o~c("B"[T>3],"H","S"[F>1])*1}	# append the sampled "BHS", conditionally including B or S if the ball/strike count is 3/2.

Losowe odniesienie „F i S”, które grało mi w głowie za każdym razem, gdy wpisałem jedną z tych liter ...

Giuseppe
źródło
2

JavaScript (SpiderMonkey) , 137 bajtów

f=(n,o='',i=Math.random()*4|0,r=/^(?!.*((B.*){4}|([SF].*){2}S|H).)/)=>r.test(o)?n?f(n-1,o+'BSFH'[i%4])||i<8&&f(n,o,i+1):!r.test(o+1)&&o:0

Wypróbuj online!

tsh
źródło
2

Pyth, 53 bajty

u+GO?H+W<K/G\B3+W<Jl@"SF"G2\F\S\B+WqK3+WgJ2\H\S\B_UQ[

Wypróbuj online tutaj .

To wydaje się zbyt długie, myślę, że może być konieczne inne podejście.

u+GO?H+W<K/G\B3+W<Jl@"SF"G2\F\S\B+WqK3+WgJ2\H\S\B_UQ[   Implicit: Q=eval(input())
                                                 _UQ    Reversed range from Q-1 to 0
u                                                   [   Reduce the above, with initial value G=[], next value as H:
                    @"SF"G                                Keep elements of G which are in "SF"
                   l                                      Length of the above
                  J                                       Store in J - this is the number of strikes and fouls so far
          /G\B                                            Count number of "B"s in G
         K                                                Store in K - this is the number of balls so far
    ?H                                                    If H is not 0 (i.e. not final pitch):
                           \F                               Start with "F" (foul is always available in non-final pitch)
                W<J       2                                 If J<2...
               +             \S                             ... append "S"
       W<K    3                                             If K<3...
      +                        \B                           ... append "B"
                                                          Else:
                                           \H               Start with "H" (hit is always available in final pitch)
                                       WgJ2                 If J >= 2...
                                      +      \S             ... append "S"
                                  WqK3                      If K == 3...
                                 +             \B           ... append "B"
   O                                                      Choose one element at random from the available options
 +G                                                       Append the above to G
                                                        Implicit print the result of the reduce operation
Sok
źródło
2

JavaScript (ES6),  107 106  99 bajtów

f=(n,k=p=s=0,o='')=>p&&p>2|k-s>3|s>2&p<2?k-n?f(n):o:f(n,k+1,o+'FSBH'[p=Math.random()*4|0,s+=p<2,p])

Wypróbuj online!

Skomentował

f = (                       // f = recursive function taking:
  n,                        //   n = requested length
  k =                       //   k = pitch counter, initialized to 0
  p =                       //   p = last pitch
  s = 0,                    //   s = sum of strikes and fouls
  o = ''                    //   o = output string
) =>                        //
  p &&                      // if the last pitch was not a foul
  p > 2 |                   // AND the last pitch was a hit
  k - s > 3 |               //     OR we have 4 balls (or 3 balls + 1 hit)
  s > 2 & p < 2 ?           //     OR more than 2 strikes or fouls, ending with a strike:
    k - n ?                 //   if k is not equal to n:
      f(n)                  //     valid series but bad timing: try again from scratch
    :                       //   else:
      o                     //     success: return o
  :                         // else:
    f(                      //   do a recursive call:
      n,                    //     n is unchanged
      k + 1,                //     increment k
      o + 'FSBH'            //     append the pitch letter to o
        [ p = Math.random() //     pick a new random pitch
              * 4 | 0,      //     in [0..3]
          s += p < 2,       //     increment s if the pitch is a foul or a strike
          p ]               //     actual index in 'FSBH'
    )                       //   end of recursive call
Arnauld
źródło
2

Atrament , 120 119 116 117 bajtów

=f(n)
->g(n,3,2)
=g(n,b,s)
~n--
{n:{~{b:b->g(n,b-1,s)}|{s:s->g(n,b,s-1)}|}f->g(n,b,s-(s>0))|{~{b:h|b}|{s:h|s}|h}}->->

Wypróbuj online!

Prawdopodobnie nadal gra w golfa.

Niegolfowany (lekko sformatowany)

=f(length) // Define a stitch f, with one parameter which specifies the length of the created string. This is the intended entry point.
->g(length,3,2) // Instantly divert to g, defined below, with some extra parameters

=g(length,balls_left,strikes_left) // Define a stitch g, with three parameters.
~ length--                         // Decrement remaining length
{
    - length: // If this is not to be the last character in the string
              // randomly do one of the following:
              // 1. If balls_left is nonzero, print a b and recurse
              // 2. If strikes_left is nonzero, print an s and recurse
              // 3. Do nothing
              // If we did not divert earlier, print an f and recurse.
        {~{balls_left:b->g(length,balls_left-1,strikes_left)}|{strikes_left:s->g(length,balls_left,strikes_left-1)}|}f->g(length,balls_left,strikes_left-(strikes_left>0)) 
    - else: // Randomly do one of the following
            // 1. If a ball would result in a walk, print a b, otherwise an h.
            // 2. If a strike would result in a strikeout, print an s, otherwise an h.
            // 3. Just print an h.
            // And finally, halt.
        {~{balls_left:h|b}|{strikes_left:h|s}|h}}->->

Edycje

  1. Zapisano bajt, kończąc na ->->zamiast zamiast ->END.
  2. Zaoszczędzono trzy bajty, zmniejszając nwcześniej.
  3. Naprawiono błąd, który powodował strajki w niewłaściwych miejscach, dzięki @veskah za wykrycie go (+1 bajt)
Sara J.
źródło
1
Na podstawie zapisu i wyników wygląda na to, że nie bierze pod uwagę fauli poprawnie zwiększających liczbę
uderzeń
1
@veskah Dobrze zauważony, należy go teraz naprawić, dzięki
Sara J
1

Węgiel drzewny , 57 bajtów

≔⁰η≔⁰ζF⊖N«≔‽⁺²‹ζ³ι¿›ι¹≦⊕ζ≦⊕η§SFB∨ι›η²»⊞υHF›η¹⊞υSF›ζ²⊞υB‽υ

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

≔⁰η≔⁰ζ

Zacznij od 0 piłek i 0 uderzeń.

F⊖N«

Pętla nad wszystkimi dostawami oprócz ostatniej.

≔‽⁺²‹ζ³ι

Jeśli były mniej niż trzy kulki, wygeneruj losową liczbę od 0 do 2, w przeciwnym razie po prostu wykonaj rzut monetą od 0 do 1.

¿›ι¹≦⊕ζ≦⊕η

Losowa wartość 2 jest piłką, w przeciwnym razie zwiększa liczbę uderzeń.

§SFB∨ι›η²»

Wartości od 0 do 2 wskazują na strajk, faul i piłkę, z tym wyjątkiem, że jeśli miałyby być trzy uderzenia, zamiast tego drukowany jest faul. (Cztery kule są wyłączone powyżej.)

⊞υHF›η¹⊞υSF›ζ²⊞υB‽υ

Ustal, czy uderzenie lub piłka wydostałoby się z pałkarza, i wybierz odpowiednio jeden lub jeden trafienie.

Neil
źródło
1

Perl 5 , 122 bajtów

map{$B=$S=$H=0;while($B<4&&$S<3&&!$H&&/./g){${$&}++;$S+=$&eq F&&$S<2}y///c>pos||push@a,$_}glob"{B,F,H,S}"x<>;say$a[rand@a]

Wypróbuj online!

Xcali
źródło
1
@Veskah Brakowało mi tej części. Naprawione.
Xcali,
1

C (GCC) 164 145 142 bajtów

-3 bajty pułap cat

#define A(a)!i&&!r--?puts(#a),++a,--n:0;
b,s,f,h,i,r;p(n){srand(time(0));for(i=n;i--;){for(n=1;n;){r=rand()&3;b>2^!A(b)s+f>1^!A(s)!A(f)A(h)}}}

Wypróbuj online

rtpax
źródło
Zaproponuj &nzamiasttime(0)
ceilingcat