Asigna un número aleatorio a pi

27

Una representación de doble precisión de un decimal solo puede garantizar una precisión de 15 decimales, por lo que pi se aproxima como:

3.141592653589793

Puede ver que el dígito 3está en posiciones 1, 10, 16, el dígito 1está en posiciones, 2, 4etc.

Reto

Su tarea es crear un programa o función que cree un número doble aleatorio entre 0 y 1, y asigne los valores de ese número al valor de pi. Para ello, coloca los diferentes dígitos en los números aleatorios en la posición que ese dígito tiene en pi. Si el dígito no se encuentra en pi, lo omitirá, y cada dígito en pi que no esté en el número aleatorio estará representado por un x. Cada valor solo se puede usar una vez, comenzando desde la izquierda.

Algunos ejemplos probablemente aclararán esto. En los siguientes ejemplos, el primer número es pi, el segundo es el número aleatorio y el último es el resultado deseado.

3.141592653589793
0.111111111111111
x.1x1xxxxxxxxxxxx

3.141592653589793
0.531000000000000
3.1xx5xxxxxxxxxxx

3.141592653589793
0.123456789123456
3.141592653x8x7xx

3.141592653589793
0.967552381459391
3.14159265358979x

Reglas:

  • La función no debe tomar ninguna entrada (una posible excepción se explica en el punto 3)
  • La salida consistirá solo en la cadena de salida, con una nueva línea opcional (también se acepta un espacio final simple)
  • Si su programa no tiene un valor Pi incorporado y / o un RNG, puede codificar Pi y tomar el número aleatorio como entrada. No puede codificar el número aleatorio o tomar Pi como entrada.
  • Tanto el valor codificado para Pi como los 15 dígitos aleatorios (puede omitir 0.ya que sabe que estará entre 0 y 1) se incluirán en el recuento de bytes.
  • Si su idioma no tiene la precisión requerida, puede usar menos precisión bajo las siguientes restricciones
    • Los dígitos de Pi deben ser precisos hasta la precisión que tenga
    • No puede generar más valores de los que se garantiza que tiene la correcta, es decir, no puede generar 15 dígitos si la precisión solo permite 8 decimales precisos.
    • El valor codificado de Pi contará como 16 bytes (no necesita el punto decimal), incluso si su programa solo admite 8 dígitos.
    • El valor de entrada para el número aleatorio contará como 15 bytes (no es necesario 0.. Esto se debe a que los idiomas con baja precisión no deberían tener una ventaja injusta.
    • El programa debe admitir 5 decimales de precisión (al menos).
    • Editar: Para validar la respuesta: el número aleatorio debe imprimirse de alguna manera, pero esta operación no tiene que incluirse en el recuento de bytes. Entonces, por ejemplo, si es posible insertar un print ral final del guión, esa parte no aumentará la puntuación.
    • No puede restar los bytes si es parte de otra operación necesaria. Es decir, si el código es print pi, r, entonces solo puedes restar , r.
    • Si tiene que insertar partes en varios lugares del código, incluya ambas versiones (la que imprime el número aleatorio y la que no lo hace con un comentario como: _py _oNoson necesarios para imprimir el número aleatorio. _pDoes xxx and _oNodoes aaa. _py _oNono se incluirán en el recuento de bytes.

El código más corto en bytes gana.


Tabla de clasificación

El Fragmento de pila al final de esta publicación genera el catálogo a partir de las respuestas a) como una lista de la solución más corta por idioma yb) como una tabla de clasificación general.

Para asegurarse de que su respuesta se muestre, comience con un título, utilizando la siguiente plantilla de Markdown:

## Language Name, N bytes

¿Dónde Nestá el tamaño de su envío? Si mejora su puntaje, puede mantener los puntajes antiguos en el título, tachándolos. Por ejemplo:

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

Si desea incluir varios números en su encabezado (por ejemplo, porque su puntaje es la suma de dos archivos o desea enumerar las penalizaciones de la bandera del intérprete por separado), asegúrese de que el puntaje real sea el último número en el encabezado:

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

También puede hacer que el nombre del idioma sea un enlace que luego aparecerá en el fragmento:

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

Stewie Griffin
fuente
2
Si está utilizando un número aleatorio incorporado, ¿tiene que contener 15 dígitos o puede tener más? ¿También hay algún requisito para generar el número aleatorio? Si no, hace un poco más difícil validar las respuestas.
user81655
¡Ah, ese es un buen punto! El número aleatorio puede tener más de 15 dígitos. Haré una edición explicando qué hacer con el número aleatorio. Gracias por comentar!
Stewie Griffin
¿Significa aleatorio " entre 0 y 1" 0 < random < 1o 0 <= random <= 1?
Chris Degnen
@StewieGriffin Estoy confundido. ¿Significa esto que podemos usar 15 dígitos de pi y un número aleatorio de 16/17 dígitos?
Jakube
@Jakube, para ser honesto: leí la pregunta un poco mal, por lo tanto respondí que podría tener más dígitos, por lo que la respuesta a su pregunta es sí. Es demasiado tarde para volver a esa respuesta ahora, ya que la mayoría de las respuestas no han limitado el número de dígitos aleatorios. Sin embargo, restringirlo a 17.
Stewie Griffin

Respuestas:

5

Pyth, 25 bytes

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

Pruébelo en línea: demostración o prueba que muestra el número aleatorio

Explicación:

 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
fuente
14

LabVIEW, 53 primitivas de LabVIEW

Combino cadenas y pongo el número en una cadena "vacía" x.xxx y elimino el número de pi para que no vuelva a aparecer.

el número aleatorio y los caracteres individuales aquí son algo visibles, ¿está bien o tengo que rehacer la grabación?

Eumel
fuente
Claramente está haciendo el trabajo, incluso si algunos caracteres son un poco difíciles de ver, por lo que no tiene que rehacer nada ... ¡Buena respuesta! =)
Stewie Griffin
6

Mathematica, 105 o 147 caracteres

Si el número aleatorio " entre 0 y 1" significa 0 <= random <= 1, es decir, incluye 0 y 1.

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

(105 caracteres)

De lo contrario, tomar el número aleatorio " entre 0 y 1" significa 0 < random < 1.

Bucle para obtener 15 enteros aleatorios, no todos cero. Seleccione el complemento del rango de 0 a 9, es decir, aquellos números del 0 al 9 que no están en la lista aleatoria. Convierta esos enteros en cadenas y reemplace los caracteres coincidentes en una cadena 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 aleatorios: -

FromDigits[r]

820307536180783
Chris Degnen
fuente
Hecho. Los saltos de línea solo se incluyen para facilitar la lectura.
Chris Degnen
2
Todavía sale como 149 bytes para mí (con saltos de línea, 146 sin). No hay nada de malo en agregar tanto una versión de golf como una de no golf. Algunos consejos de golf: Truees decir 1>0, RandomIntegerpuede usar la notación infija {0,9}~RandomInteger~15. Probablemente pueda guardar algunos bytes dando ralgún valor y, de hecho, utilizando la condición de en Whilelugar de usar Break.Then Forpodría guardar otro byte While. Aunque no entiendo por qué necesita el bucle si asume el número aleatorio en el rango [0,1).
Martin Ender
@ MartinBüttner Me gusta 1>0:-)
Chris Degnen
Normalmente leería un número aleatorio "entre 0 y 1" para significar 0 <aleatorio <1.
Chris Degnen
5

JavaScript (ES6), 89 87 bytes

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

Explicación

Editar: la cadena aleatoria ahora no se trunca como lo aclara el póster.

Recorre cada dígito de pi y elimina el dígito del número aleatorio si se encontró, de lo contrario, reemplaza el dígito en pi con 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
    ))

Prueba

La prueba también genera el número aleatorio.

usuario81655
fuente
¿No podría random () producir 15 ceros en los que correspondería a 0.000 ... o 1.000 ...? es decir, no entre 0 y 1.
Chris Degnen
@ChrisDegnen Math.random()produce un número del rango, [0,1)por lo que podría 0pero nunca 1. El OP no especificó específicamente si el rango era inclusivo o exclusivo, por lo que supuse que todo lo que fuera razonable está bien. Este es también el rango que utilizan las otras respuestas. Sin embargo, me has hecho consciente de que si es exactamente 0fallará porque .in pi no coincidirá y se convertirá x. Esto tiene una probabilidad de 1 en 2 ^ 53 de ocurrir, pero decidí arreglarlo de todos modos.
user81655
:-) lo siento por eso.
Chris Degnen
La probabilidad de acertar exactamente 0 o 1 para un doble aleatorio es insignificante, por lo que para este desafío un rango [0,1]está bien (también lo es (0,1)).
Stewie Griffin
Agradable. Propongo una variante más corta.
MST
3

CJam, 48 46 42 38 36 bytes

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

Pruébalo aquí.

Y aquí está la versión que imprime tanto π como el número aleatorio:

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

Pruébalo aquí.

No trunco ​​el número aleatorio a 15 decimales, como lo aclara el OP en un comentario.

Explicación

La idea es convertir cada carácter en la representación de cadena de π en un par de ese carácter y x. Para cada carácter en el número aleatorio, intercambiamos el primer par que comienza con ese carácter. Al final sacamos el segundo carácter 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
fuente
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)

Explicaciones

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

Lamentablemente, lua no me ayuda en absoluto aquí. math.pi alrededor del último dígito de pi devuelve:

print(math.pi)
>> 3.1415926535898

Tengo que truncar este número:

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

El segundo gran defecto para hacer este desafío fue la falta de string.replace (). Como estoy haciendo esta acción dos veces s:sub(1,l-1)..c..s:sub(l+1), quería hacer una función anónima, pensando que sería más corta. No lo es, así que lo escribí dos veces.

La razón por la que tengo que tener cuidado con el punto, es cómo lua vuelve a su posición. En expresiones regulares, un punto significa "cualquier carácter", por lo que cuando estoy evaluando el carácter .en mi bucle, coincide con el primer carácter:

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 

Puedes probar lua en línea . Como no estoy enviando el PRNG, aquí hay un código que le permite ejecutar varias pruebas sin dejar de ver los 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
fuente
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`)

Probado en la última aplicación de Android QPython, pero debería funcionar en cualquier lugar.

Edición 1: cambiado str(pi)a backticks.

Para las pruebas:

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
fuente
¡Buena respuesta! Los "apóstrofes que SO usa para marcar el código" son backticks o símbolos de arboleda, por cierto :-)
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 autoexplicativo: la función lambda convierte flotante a lista; luego recorremos la lista pi intentando eliminar cada dígito de la lista aleatoria. Si podemos, bien, añádelo a la respuesta; si no, agregue una 'x' en su lugar.

Kieran Hunt
fuente
str(t)solo le da 11 dígitos de precisión t, repr(t)le da todos tlos 15 dígitos de.
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

Con comentarios:

$_=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 versión imprimirá pi, el número aleatorio y el 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"

Salida de ejemplo:

3.14159265358979
0.877757977767946
x.x4x59x6xxx897x

Espero que esté bien:

  • pi contiene 15 dígitos en total, incluidos los 3, por lo que no supera la precisión.
  • El último dígito ( 9) es exacto.
Kenney
fuente