Gere uma corda de campo de beisebol

11

Objetivo

Escreva um programa ou função que use um número inteiro positivo ne gere aleatoriamente uma série legal de arremessos (doravante denominada sequência de afinação) de comprimento n.

Entrada

Um número inteiro positivo diferente de zero n<= 100

Resultado

Retorne uma sequência aleatória, ou lista de caracteres, que represente uma sequência de lançamentos possível e válida n. Os caracteres utilizados serão:

  • B - bola. Se você acumular 4 delas, a massa é levada e terminada.
  • S - greve. Se você acumular 3 delas, a massa está fora e terminou de rebater.
  • F - Falta. Também aumentará a contagem de Strike, mas não conseguirá eliminar a massa. Ou seja, você não pode ter uma falta como o último arremesso em uma sequência válida. Quaisquer faltas após dois ataques / faltas não aumentarão a contagem de ataques (o batedor já tem 2 ataques nesse ponto e um terceiro o eliminaria).
  • H - Hit. A massa bateu uma bola em jogo e terminou de rebater.

(Isso é um pouco simplificado, mas não se preocupe com isso)

Strings de pitch válidas são aquelas que terminam em um strike-out, uma caminhada ou um hit.

Ou seja, uma sequência de afinação inválida tem

  • arremessos adicionais após a 4ª bola, 3ª batida ou batida
  • terminado antes de gerar uma quarta bola, um terceiro golpe ou um golpe.

Regras

  • Seu programa deve ser capaz de produzir todos os resultados possíveis para uma determinada entrada.
  • Seu programa não precisa ser uniformemente aleatório, mas ainda deve seguir a regra anterior.
  • Isso é .

Exemplos

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
fonte
1
Então, temos que ser capazes de produzir algo entre 1 e F infinito?
Quintec 27/02/19
A sequência terá no máximo 100 caracteres. Faltas são o que permite cordas de arremesso tão longas, por exemplo, 99 se Fum Sé um strike-out
Veskah 27/02/1919
Ah, entendi, perdi isso
Quintec 27/02/19
A @Quintec reformulou para ser um pouco mais explícito, apenas por precaução.
Veskah 27/02/19

Respostas:

4

Python 2 , 128 bytes

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)

Experimente online!

Gere aleatoriamente a corda do arremesso até que a massa esteja pronta, produza-a se tiver o comprimento certo e tente novamente do zero.


Python 2 , 136 bytes

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)

Experimente online!

xnor
fonte
O exemplo de Kevin disso me fez perceber que isso ocorre por números mais altos. n=8pode gerar uma cadeia de Fs no final
Veskah 27/02/19
2
@Veskah Boa captura. Eu não tinha contabilizado a contagem de greves (contando faltas) possivelmente subindo para 6, e mudando S/3para (S>2)corrigi-la.
xnor
4

05AB1E ,  44  50 44 bytes

Riscado &nbsp;44&nbsp;já não é 44 :)

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

Porta da resposta Python 2 do @xnor , por isso, certifique-se de vomitá-lo também se você gosta desta resposta!
+6 bytes devido a uma correção de bug e, depois disso, -6 bytes novamente, graças ao @xnor , portando sua correção mais eficiente em comparação com minha solução temporária, como eu esperava. ;)

Experimente online ou verifique mais resultados aleatórios .

Explicação:

[                # 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
fonte
1
@Veskah Fiz uma correção direta por enquanto. Tenho a sensação de que o xnor é capaz de fazer uma correção mais curta, então provavelmente portarei a correção para salvar alguns bytes mais tarde. :)
Kevin Cruijssen 27/02/19
1
Você pode corrigi-lo como eu fiz ao mudar X/3para X>2.
xnor
@xnor Obrigado, voltando aos 44 bytes novamente. Eu sabia que você encontraria algo mais curto. ; p
Kevin Cruijssen 28/02/19
3

R , 148 bytes

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}

Experimente online!

Gera a sequência, usando a inclusão condicional nos conjuntos de dados de amostra para garantir que o resultado seja uma possível sequência de afinação.

Possivelmente a amostragem de rejeição (como a resposta python do xnor faz ) é mais curta.

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.

Referência aleatória de "F e S" que ficava tocando na minha cabeça toda vez que eu digitava uma dessas letras ...

Giuseppe
fonte
2

JavaScript (SpiderMonkey) , 137 bytes

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

Experimente online!

tsh
fonte
2

Pitão, 53 bytes

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

Experimente online aqui .

Parece demais, acho que pode ser necessária outra abordagem.

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
fonte
2

JavaScript (ES6),  107 106  99 bytes

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])

Experimente online!

Comentado

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
fonte
2

Tinta , 120 119 116 117 bytes

=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}}->->

Experimente online!

Provavelmente ainda jogável.

Ungolfed (levemente reformatado)

=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}}->->

Editar% s

  1. Salva um byte ao terminar com em ->->vez de ->END.
  2. Salva três bytes decrementando nanteriormente.
  3. Corrigido um bug que causava ataques em locais incorretos, graças a @veskah por detectá-lo (+1 byte)
Sara J
fonte
1
Com base no write-up e saídas, parece que isso não acontece fator faltas incrementando a greve de contar corretamente
Veskah
1
@veskah Bem visto, deve ser fixado agora, graças
Sara J
1

Carvão vegetal , 57 bytes

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

Experimente online! Link é a versão detalhada do código. Explicação:

≔⁰η≔⁰ζ

Comece com 0 bolas e 0 acertos.

F⊖N«

Repetir todas as entregas, exceto a última.

≔‽⁺²‹ζ³ι

Se houver menos de três bolas, gere um número aleatório de 0 a 2, caso contrário, basta trocar de moeda entre 0 e 1.

¿›ι¹≦⊕ζ≦⊕η

Um valor aleatório de 2 é uma bola; caso contrário, aumenta a contagem de ataques.

§SFB∨ι›η²»

Os valores de 0 a 2 são mapeados para a tacada, falta e bola, exceto que, se houver três tacadas, a falta será impressa. (Quatro bolas estão excluídas acima.)

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

Determine se um ataque ou bola levaria a bola para fora e escolha entre aqueles ou um golpe, conforme apropriado.

Neil
fonte
1

Perl 5 , 122 bytes

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]

Experimente online!

Xcali
fonte
1
@Veskah, perdi essa parte. Corrigido.
Xcali 17/07/19
1

C (GCC) 164 145 142 bytes

-3 bytes ceilingcat

#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)}}}

Experimente online

rtpax
fonte
Sugerir em &nvez detime(0)
ceilingcat 27/01