Mapear um número aleatório para pi

27

Uma representação de precisão dupla de um decimal só pode garantir uma precisão de 15 casas decimais, portanto, pi é aproximado como:

3.141592653589793

Você pode ver que o dígito 3está nas posições 1, 10, 16, o dígito 1está nas posições, 2, 4etc.

Desafio

Sua tarefa é criar um programa ou função que crie um número duplo aleatório entre 0 e 1 e mapeie os valores desse número no valor de pi. Você faz isso colocando os diferentes dígitos nos números aleatórios na posição que o dígito possui em pi. Se o dígito não for encontrado em pi, você o ignorará e todos os dígitos em pi que não estejam no número aleatório serão representados por um x. Cada valor pode ser usado apenas uma vez, começando pela esquerda.

Alguns exemplos provavelmente tornarão isso mais claro. Nos exemplos a seguir, o primeiro número é pi, o segundo é o número aleatório e o último é a saída desejada.

3.141592653589793
0.111111111111111
x.1x1xxxxxxxxxxxx

3.141592653589793
0.531000000000000
3.1xx5xxxxxxxxxxx

3.141592653589793
0.123456789123456
3.141592653x8x7xx

3.141592653589793
0.967552381459391
3.14159265358979x

Regras:

  • A função não deve receber nenhuma entrada (uma possível exceção é explicada no ponto 3 do marcador)
  • A saída deve consistir apenas na sequência de saída, com uma nova linha opcional (um único espaço à direita também é aceito)
  • Se o seu programa não possui um valor Pi incorporado, e / ou um RNG, você pode codificar Pi e pegar o número aleatório como entrada. Você não pode codificar o número aleatório ou usar o Pi como entrada.
  • Tanto o valor codificado para Pi quanto os 15 dígitos aleatórios (você pode pular, 0.pois sabe que ficará entre 0 e 1), serão incluídos na contagem de bytes.
  • Se o seu idioma não tiver a precisão necessária, você poderá usar menos precisão nas seguintes restrições
    • Os dígitos do Pi devem ser precisos até a precisão que você possui
    • Você não pode produzir mais valores do que os que estão garantidos, ou seja, não pode produzir 15 dígitos se a precisão permitir apenas 8 casas decimais precisas.
    • O valor codificado do Pi contará como 16 bytes (você não precisa do ponto decimal), mesmo se o seu programa suportar apenas 8 dígitos.
    • O valor de entrada para o número aleatório contará como 15 bytes (você não precisa 0.. Isso ocorre porque idiomas com baixa precisão não devem ter uma vantagem injusta.
    • O programa deve suportar precisão de 5 casas decimais (pelo menos).
    • Editar: para validar a resposta: O número aleatório deve ser impresso de alguma forma, mas esta operação não precisa ser incluída na contagem de bytes. Por exemplo, se for possível inserir um print rno final do script, essa parte não aumentará a pontuação.
    • Você não pode subtrair os bytes se fizer parte de outra operação necessária. Ou seja, se o código for print pi, r, você poderá subtrair apenas , r.
    • Se você precisar inserir partes em vários lugares do código, inclua as duas versões (aquela que imprime o número aleatório e a que não imprime com um comentário como: _pe _oNoé necessária para imprimir o número aleatório. _pFaz xxx e _oNofaz yyy. _pe _oNonão será incluído na contagem de bytes.

O código mais curto em bytes vence.


Entre os melhores

O snippet de pilha na parte inferior desta postagem gera o catálogo a partir das respostas a) como uma lista da solução mais curta por idioma eb) como uma tabela geral de líderes.

Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:

## Language Name, N bytes

onde Nestá o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Se você quiser incluir vários números no cabeçalho (por exemplo, porque sua pontuação é a soma de dois arquivos ou você deseja listar as penalidades do sinalizador de intérpretes separadamente), verifique se a pontuação real é o último número no cabeçalho:

## Perl, 43 + 2 (-p flag) = 45 bytes

Você também pode transformar o nome do idioma em um link que será exibido no snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes

Stewie Griffin
fonte
2
Se você estiver usando um número aleatório interno, ele deve conter 15 dígitos ou pode ter mais? Também existem requisitos para gerar o número aleatório? Caso contrário, fica um pouco mais difícil validar respostas.
user81655
Aah, esse é um bom argumento! O número aleatório pode ter mais de 15 dígitos. Vou fazer uma edição explicando o que fazer com o número aleatório. Obrigado por comentar!
Stewie Griffin
Aleatório " entre 0 e 1" significa 0 < random < 1ou 0 <= random <= 1?
precisa saber é o seguinte
@StewieGriffin Estou confuso. Isso significa que podemos usar 15 dígitos de pi e um número aleatório de 16/17 dígitos?
Jakube
@Jakube, para ser sincero: eu li a pergunta um pouco errado, respondi que poderia ter mais dígitos, então a resposta para sua pergunta é sim. É tarde demais para voltar a responder agora, já que a maioria das respostas não limitou o número de dígitos aleatórios. No entanto, restrinja-o a 17.
Stewie Griffin

Respostas:

5

Pitão, 25 bytes

 u&p?}HGH\x.-GH`.n0<`O017

Experimente on-line: demonstração ou teste mostrando o número aleatório

Explicação:

 u&p?}HGH\x.-GH`.n0<`O017  
                .n0         the constant pi
               `            convert it into a string
                     O0     random number in the range [0.0, 1.0)
                    `       convert to string
                   <   17   only use the first 17 chars (zero, point and 15 digits)
 u                          for each char H in the pi-string:
    ?}HGH\x                    if H in G (the random number string) then H else "x"
   p                           print this char without newline
  &                            and
           .-GH                remove the digit H once from G
<space>                     suppress the output (u returns the unused digits in G)
Jakube
fonte
14

LabVIEW, 53 Primitivas do LabVIEW

Combino Strings e coloco o número em uma string x.xxx "vazia" e removo o número de pi para que não apareça novamente.

o número aleatório e os caracteres únicos aqui são meio visíveis, está tudo bem ou eu tenho que refazer a gravação?

Eumel
fonte
Está claramente fazendo o trabalho, mesmo que alguns caracteres sejam um pouco difíceis de ver, para que você não precise refazer nada ... Boa resposta! =)
Stewie Griffin
6

Mathematica, 105 ou 147 caracteres

Se um número aleatório " entre 0 e 1" significa 0 <= random <= 1, ou seja, inclui 0 e 1.

StringReplace[ToString@InputForm@N@Pi,
Thread[ToString/@Complement[Range@9,RandomInteger[{0,9},15]]->"x"]]

(105 caracteres)

Caso contrário, pegue o número aleatório " entre 0 e 1" para significar 0 < random < 1.

Faça um loop para obter 15 números inteiros aleatórios, nem todos zero. Selecione o complemento de 0 a 9, ou seja, os números de 0 a 9 que não estão na lista aleatória. Converta esses números inteiros em cadeias e substitua os caracteres correspondentes em uma cadeia pi.

(147 caracteres)

While[True,r=RandomInteger[{0,9},15];
If[Union@r!={0},Break[]]];
StringReplace[ToString@InputForm@N@Pi,
Thread[ToString/@Complement[Range@9,r]->"x"]]

3.1x15x265358x7x3

Dígitos aleatórios: -

FromDigits[r]

820307536180783
Chris Degnen
fonte
Feito. Quebras de linha incluídas apenas para facilitar a leitura.
precisa saber é o seguinte
2
Ainda sai como 149 bytes para mim (com quebras de linha, 146 sem). Não há nada de errado em adicionar uma versão tanto para golfe quanto para uma versão sem golfe. Algumas dicas de golfe: Trueé 1>0, RandomIntegerpode usar notação infix {0,9}~RandomInteger~15. Provavelmente, você pode salvar alguns bytes, fornecendo ralgum valor e, na verdade, usando a condição de, em Whilevez de usar Break.Then, Forpode salvar outro byte While. Embora eu não entenda por que você precisa do loop, se assume o número aleatório no intervalo [0,1).
Martin Ender
@ MartinBüttner Gosto de 1>0:-) #
7897 Chris Degnen
Normalmente, eu leria o número aleatório "entre 0 e 1" para significar 0 <aleatório <1. #
Chris Degnen 21/12/2015
5

JavaScript (ES6), 89 87 bytes

_=>(r=[...Math.random()+""],Math.PI+"").replace(/./g,d=>(r[i=r.indexOf(d)]=_,~i?d:"x"))

Explicação

Edit: String aleatória agora não é truncada conforme esclarecido pelo pôster.

Faz um loop em cada dígito de pi e remove o dígito do número aleatório, se for encontrado, caso contrário, substitui o dígito em pi por x.

_=>(
    r=[...Math.random()+""],      // r = array of 15 digit random number chars
    Math.PI+"").replace(/./g,d=>( // for each digit d of pi, includes "." which is always
                                  //     in the random number
      r[i=r.indexOf(d)]=_,        // i = position of d within r, remove digit from r
                                  // "_" is the unused function argument (equals undefined)
      ~i?d:"x"                    // if found, leave the digit, else replace with x
    ))

Teste

Teste gera também o número aleatório.

user81655
fonte
Não foi possível random () produzir 15 zeros nos quais corresponderia a 0,000 ... ou 1.000 ...? ou seja, não entre 0 e 1.
Chris Degnen
O @ChrisDegnen Math.random()produz um número da faixa [0,1)para que pudesse, 0mas nunca 1. O OP não especificou especificamente se o intervalo era inclusivo ou exclusivo, por isso presumi que tudo o que fosse razoável fosse bom. Esse também é o intervalo que as outras respostas usam. No entanto, você me informou que, se for exatamente 0, falhará porque o .in pi não será correspondido e se tornará x. Isso tem uma chance de 1 em 2 ^ 53, mas eu decidi corrigi-lo de qualquer maneira.
user81655
:-) desculpa aí.
precisa saber é o seguinte
A probabilidade de atingir exatamente 0 ou 1 para um duplo aleatório é insignificante; portanto, para o objetivo desse desafio, um intervalo [0,1]é bom (o que é (0,1)).
Stewie Griffin
Agradável. Proponho uma variante mais curta.
MST
3

CJam, 48 46 42 38 36 bytes

P`'xf+1dmr`{1$f#:!1a/0=:)W+H<.%}/1f=

Teste aqui.

E aqui está a versão que imprime π e o número aleatório:

P_p`'xf+1dmr`_oNo{1$f#:!1a/0=:)W+H<.%}/1f=

Teste aqui.

Não trunfo o número aleatório para 15 casas decimais, conforme esclarecido pelo OP em um comentário.

Explicação

A idéia é transformar cada caractere na representação em cadeia de π em um par desse caractere e x. Para cada caractere no número aleatório, trocamos o primeiro par que começa com esse caractere. No final, produzimos o segundo caractere de cada par.

P`      e# Get string representation of π.
'xf+    e# Append "x" to each character.
1dmr`   e# Get string representation of random number in [0,1).
{       e# For each character in that string...
  1$    e#   Copy the list of pairs.
  f#    e#   For each pair, find the index of the current character. If the character is
        e#   not in the pair, we get -1 (truthy). If it is the first character of the pair,
        e#   we get 0 (falsy). If it is the second character, we get 1 (truthy).
  :!    e#   Logical NOT for each of the results. We get a 1 for every pair we could
        e#   potentially swap.
  1a/   e#   Split around those 1s.
  0=    e#   Keep only the first chunk.
  :)    e#   Turn all the 0s into that chunk into 1s.
  W+    e#   Append a -1.
  H<    e#   Truncate to 17 elements (the number of pairs).
  .%    e#   Apply % pairwise. This reverses the element at the position of the -1.
}/
1f=     e# Select the second character from each pair.
Martin Ender
fonte
2

Lua, 231 230 bytes

m,s=math,""p,r=m.pi..s,s..m.random()p=p:sub(1,#p-1)p:gsub(".",function(c)s=s..(47>c:byte()and c or"x")end)r:gsub("[^%.]",function(c)l=p:find(c)if l then p,s=p:sub(1,l-1).."x"..p:sub(l+1),s:sub(1,l-1)..c..s:sub(l+1)end end)print(s)

Explicações

function f()
  m,s=math,""
  p,r=m.pi..s,s..m.random()
  p=p:sub(1,#p-1)                       -- remove the last digit of math.pi

  p:gsub(".",function(c)
    s=s..(47>c:byte()and c or"x")      -- Construct a string full of "x" with a single dot
  end)

  r:gsub("[^%.]",function(c)            -- Iterate over each character but the dot in the random number
    l=p:find(c)                         -- if c isn't in pi, l=nil 
    if l                                -- which is one of the two falsy value in lua
    then
      p,s=p:sub(1,l-1).."x"..p:sub(l+1),-- If c is in pi, we replace it in p by an x
          s:sub(1,l-1)..c..s:sub(l+1)   -- and in s by its value
    end
  end)
  return s
end

Infelizmente, lua não me ajuda em nada aqui. math.pi em volta do último dígito de pi, ele retorna:

print(math.pi)
>> 3.1415926535898

Eu tenho que truncar este número:

stringPI=""..math.pi
print(stringPI:sub(1,#stringPI-1))
>> 3.141592653589

O segundo grande padrão para fazer esse desafio foi a falta de string.replace (). Como eu estou fazendo essa ação duas vezes s:sub(1,l-1)..c..s:sub(l+1), eu queria fazer uma função anônima, pensando que seria mais curta. Não é, então eu o escrevi duas vezes.

A razão pela qual tenho que ter cuidado com o ponto é como a lua retorna à sua posição. Nas expressões regulares, um ponto significa "qualquer caractere"; portanto, quando estou avaliando o caractere .no meu loop, ele corresponde ao primeiro caractere:

c="."  -- The value of the dot in the loop
found = stringPI:find(c)
print(stringPI)
print("location of \".\": "..found)
print("char at "..found..": "..stringPI:sub(found,found))

>> 3.141592653589
>> location of ".": 1   --Keep in mind that lua arrays are 1-based :)
>> char at 1: 3 

Você pode testar a lua online . Como não estou propagando o PRNG, aqui está um código que permite executar vários testes enquanto ainda observa valores.

function f()m,s=math,""p,r=m.pi..s,s..m.random()print("Random number: "..r)p=p:sub(1,#p-1)p:gsub(".",function(c)s=s..(c:byte()<47 and c or"x")end)r:gsub("[^%.]",function(c)l=p:find(c)if l then p,s=p:sub(1,l-1).."x"..p:sub(l+1),s:sub(1,l-1)..c..s:sub(l+1)end end)return s end

for i=1,10
do
    print(f())
end
Katenkyo
fonte
2

Python 2.7, 117 110 bytes

import math,random
n=list(`random.random()`)
print''.join(n.pop(n.index(d))if d in n else'x'for d in`math.pi`)

Testado no aplicativo Android QPython mais recente, mas deve funcionar em qualquer lugar.

Edit 1: alterado str(pi)para backticks.

Para teste:

import math,random
n=list(`random.random()`)
print `math.pi`
print ''.join(n)
print''.join(n.pop(n.index(d))if d in n else'x'for d in`math.pi`)
uryga
fonte
Boa resposta! Os "apóstrofos que o SO usa para marcar o código" são reticulares ou símbolos de bosque, a propósito :-)
cat
1

Python, 147 bytes

import math as m,random as r
L=lambda t:[_ for _ in str(t)]
p=L(m.pi)
R=L(r.random())
A=""
print R #subtracted from byte count
for n in p:
    try:R.remove(n);A+=n
    except:A+='x'
print A

Bastante auto-explicativo: a função lambda converte float em lista; em seguida, percorreremos a lista pi tentando remover cada dígito da lista aleatória. Se pudermos, acrescente-o à resposta; caso contrário, adicione um 'x'.

Kieran Hunt
fonte
str(t)fornece apenas 11 dígitos de precisão t, repr(t)fornece todos tos 15 dígitos.
Noodle9
1

Perl, 70 bytes

$_=4*atan2(1,1);s/\d/x$&/g;for$i(rand=~/\d/g){s/x$i/$i/}s/x./x/g;print

Com comentários:

$_=4*atan2(1,1);        # Perl doesn't have a Pi constant
s/\d/x$&/g;             # prepend a x to all digits in Pi
for $i (rand=~/\d/g)    # iterate the digits in the random number
{ s/x$i/$i/ }           # replace first occurrence of x-nr pair 
s/x./x/g;               # strip all remaining numbers
print                   # print!

Esta versão imprimirá pi, o número aleatório e o resultado:

$_=$p=4*atan2(1,1);
s/\d/x$&/g;
$r=rand;
for $i ($r=~/\d/g)
{ s/x$i/$i/ }
s/x./x/g;
print "$p\n$r\n$_\n"

Exemplo de saída:

3.14159265358979
0.877757977767946
x.x4x59x6xxx897x

Espero que isso esteja bem:

  • pi contém 15 dígitos no total, incluindo os 3, para que não exceda a precisão.
  • o último dígito ( 9) é preciso.
Kenney
fonte