Determine la base donde una ecuación dada es verdadera


22

Dados 3 enteros, determine la base más baja posible para que los primeros dos enteros se multipliquen en el tercero. Si piensa en la respuesta a la última pregunta de la vida, el universo y todo, 6 * 9 == 42, es cierto en la Base 13.

Las entradas pueden incluir cualquier número cuyos dígitos usen los caracteres 0-9, az y AZ, donde aes igual a 10 en Base 10 y Zes 61 en Base 10.

Las entradas deben ingresarse de la forma que desee (excepto la codificación rígida), y puede escribir una función individual o un programa completo.

La base máxima que debe considerarse es la Base 62, y la base mínima es la Base 2.

Puede suponer que los dos primeros valores son más pequeños que el tercero. También puede concluir que la base mínima es uno mayor que el dígito / carácter más alto de las entradas (por ejemplo, si las entradas son 3 1a 55, la base mínima sería Base 11, porque aes el dígito más alto).

Si no existe tal base, devuelva un valor basura de su elección.

Este es el código de golf, por lo que gana el código más corto.

Casos de prueba

6 9 42     -->   13
a a 64     -->   16
aA bB 36jk -->   41
2 3 20     -->   <junk value>
10 10 100  -->   2

Creo que STDIN probablemente sería mejor, y cualquiera estaría bien.
erdekhayser

@ MartinBüttner Entonces, ¿debo permitir la entrada en cualquier forma?
erdekhayser

1
Como punto de aclaración, qué se debe hacer si varias bases son válidas, como su último ejemplo (que ahora se ha eliminado, era 10 * 10 = 100) donde también es válido en la base 10 y, de hecho, en cualquier otra base que le interese mencionar ...
Chris

1
@Kay Si defino el sistema posicional en base bde una manera general como a_0 b^0 + a_1 b^1 + a_2 b^2 + ...(donde a_0es el dígito menos significativo) que la base 1 definitivamente tiene sentido. Además, la conclusión del OP también incluiría la base 1 en la búsqueda si el dígito actual más grande es 0.
Martin Ender

2
Sobre la base 1, unario es un sistema numérico. en.m.wikipedia.org/wiki/Unary_numeral_system
erdekhayser

Respuestas:


3

CJam, 52 51 48 bytes

63,{_ea{i32b~\([G-35-9]=-_Xe>:X;}f%fbW%~*=\X>*}#

Pruébalo aquí. El probador en línea no admite entradas a través de ARGV. La alternativa más cercana es poner poner la entrada como 6 9 42en STDIN y usar:

lS/:E;
63,{_E{i32b~\([G-35-9]=-_Xe>:X;}f%fbW%~*=\X>*}#

Esto se imprime -1si no se puede encontrar una base válida hasta 62.

¡Muchas gracias a Peter por el código de análisis de dígitos!

Solucioné muchos problemas que agregaron 14 bytes al recuento. La siguiente explicación sigue siendo para mi presentación original, y la actualizaré mañana.

63,{_ea{i32b~\([G-35-9]=-_Xe>:X;}f%fbW%~*=\X>*}#
63,                                              "Push the array [0 1 .. 62].";
   {                                          }# "Find the first index for which the block returns
                                                  a truthy value.";
    _                                            "Duplicate the current base.";
     ea                                          "Read ARGV into an array of strings.";
       {                        }f%              "Apply this block to each character.";
        i32b                                     "Convert to code point, and then to base-32. The
                                                  most significant digit now identifies the 'type'
                                                  of digit.";
            ~\(                                  "Unwrap the array. Swap the digits. Decrement.";
               [G-35-9]                          "Push array [16 -35 -9] of digit offsets.";
                       =-                        "Select the relevant offset and subtract it from 
                                                  the least significant digit.";
                         _                       "Duplicate the current digit D.";
                          Xe>:X;                 "X := max(X,D). X is predefined as 1.";
                                   fb            "Convert all numbers to the current base.";
                                     W%          "Reverse the list of numbers.";
                                       ~         "Unwrap the array.";
                                        *=       "Multiply factors. Check equality with product.";
                                          \      "Swap result with current base.";
                                           X>    "Ensure base is greater than X.";
                                             *   "Multiply boolean results.";

El índice se imprime automáticamente al final del programa.


En GS, los dígitos se pueden analizar como 32base~\[-16.35 9]=+. Sé que CJam tiene una conversión de base más corta.
Peter Taylor

7

APL (Dyalog Unicode) , SBCS de 30 bytes

⊢{3e=×/2e←⍵⊥⍺:⍵⋄⍺∇⍵+1}1+⌈/∘,

Pruébalo en línea!

Gracias a Adám por la ayuda.

Explicación:

⊢{3e=×/2e←⍵⊥⍺:⍵⋄⍺∇⍵+1}1+⌈/∘,  
                               left argument ⍺: the vector (do nothing)
                        1+⌈/∘,  right argument ⍵: our starting base.
                             ,              start by flattening the matrix of arguments                               ⌈/                reduce by max (find the highest number)
                                           compose both of these together
                        1+                  increment by one
 {         ⍵⊥⍺         }        convert inputs to the current base
 {       e            }        store the converted values in 3
 {      2             }        take the first 2 values
 {    ×/               }        multiply them together (reduce-multiply)
 {  e=                 }        compare with e (the converted inputs)
 {3                   }        only keep the result of the comparison with the 3rd element (expected result)
 {             :⍵      }        if truthy, return the current base.
 {                    }        otherwise...
 {                ⍺∇⍵+1}        ...recurse with the base incremented

Usamos una función auxiliar In, para recibir la entrada en un formato más aceptable. De lo contrario, la entrada recibe una matriz de 3 columnas.

'3 9 42' daría, por ejemplo (leer de arriba hacia abajo y luego de izquierda a derecha):

0 0 4
3 9 2

Y para 'aA bB 36jk'(lo mismo aquí. aEs 10, bes 11, Aes 36, etc.)

 0  0  3
 0  0  6
10 11 19
36 37 20

2

Pitón 2 - 197 213

Qué monstruo ... (en comparación con CJam)

from string import*
I=raw_input()
x,y,z=I.split()
B=lambda s,b:sum(b**i*(digits+lowercase+uppercase).find(s[-i-1])for i in range(len(s)))
print([b for b in range(B(max(I),10)+1,62)if B(x,b)*B(y,b)==B(z,b)]+[0])[0]

Desafortunadamente int, la conversión de bases solo puede manejar bases de hasta 36. Por lo tanto, necesitaba implementarla yo mismo. (Vea esta maravillosa solución ).


¿Esto se asegura de no devolver una base menor o igual a los dígitos más grandes?
Martin Ender

@ MartinBüttner: no estoy seguro. Al menos no explícitamente. ¿Tiene un caso de prueba donde esto es un problema? (En realidad, la generación de casos de prueba debe ser atendida por el OP ...)
Falko

Pruebe 2 * 3 = 20 que tiene base 3 en un caso de error. 3 no es un dígito en un sistema de numeración ternario.
kay

2

CJam, 53 bytes

lA,s'{,97>+'[,65>+f#_$W=1e>)63,>_@Wa/W%f{fb~*=}1#\0+=

Toma las tres entradas de STDIN como

6 9 42

Imprime 0si el producto en cualquier base no es posible

Intentará jugar más al golf.

Pruébalo aquí


1

JavaScript (E6) 129 139

Pruebe recursivamente todas las bases desde 2 hasta 62, devolviendo -1 si ningún valor está bien.
La función parseInt de JavaScript funciona con una base de hasta 36, ​​por lo que se necesita un poco de ayuda para bases más grandes.
Cuidado, los parámetros x, y, z son cadenas, no números.
Es más difícil de lo que parece. Gracias a Martin por señalar un error básico en la primera versión.

F=(x,y,z,b=2,N=n=>[for(d of(t=0,n))t=(v=parseInt(d,36)+(d>'@'&d<'a')*26)<b?t*b+v:NaN]&&t)=>b<63?N(x)*N(y)!=N(z)?F(x,y,z,b+1):b:-1

Menos golf

F=(x,y,z,b=2,
   D=d=>parseInt(d,36)+(d>'@'&d<'a')*26, // parse a single digit
   N=n=>[for(d of(t=0,n))t=(v=D(d))<b?t*b+v:NaN]&&t // parse a string
)=>b<63?N(x)*N(y)!=N(z)?F(x,y,z,b+1):b:-1

Prueba en la consola FireFox / FireBug.
La prueba prueba 1000 números con diferentes bases (hasta 36, ​​no 62). Vale la pena señalar que la base encontrada podría ser correcta pero menor que la base que generó el caso de prueba.

for(i=0;i<1000;i++)
{
   x=Math.random()*100|0,y=Math.random()*100|0,z=x*y,b=Math.random()*35+2|0
   bx=x.toString(b),by=y.toString(b),bz=z.toString(b),
   nb=F(bx,by,bz)
   nx=parseInt(bx,nb),ny=parseInt(by,nb),nz=parseInt(bz,nb)
   // if (nx*ny != nz) // uncomment to se output for errors only
     console.log(x,y,z,'base '+b,bx,by,bz, 'found base '+nb,nx,ny,nz,nx*ny)
}

@ MartinBüttner los parámetros son cadenas (ya que los valores posibles son algo así como aA bB 36jk ...). Aclarado en la respuesta.
edc65

Oh cierto, eso tiene sentido.
Martin Ender

1

Carbón , 28 bytes

I⌊Φ…⊕⍘⌈⁺⁺θηζ⁶²¦⁶³⁼×⍘θι⍘ηι⍘ζι

Pruébalo en línea! El enlace es a la versión detallada del código. Salidas Nonesi no se puede encontrar una base válida. Explicación:

         θ                      First input
        ⁺                       Concatenated with
          η                     Second input
       ⁺                        Concatenated with
           ζ                    Third input
      ⌈                         Maximum character (by ordinal)
     ⍘                          Converted from base
            ⁶²                  Literal 62
    ⊕                           Incremented
   …                            Range up to
               ⁶³               Literal 63
  Φ                             Filtered by
                    θ           First input
                   ⍘            Converted from base
                     ι          Current value
                  ×             Multiplied by
                       η        Second input
                      ⍘         Converted from base
                        ι       Current value
                 ⁼              Equals
                          ζ     Third input
                         ⍘      Converted from base
                           ι    Current value
 ⌊                              Minimum
I                               Cast to string
                                Implicitly print

¿Es posible tener un programa TIO que use el código real que publicó?
mbomb007

@ mbomb007 ¡Puedes probarlo en línea! pero el generador AST parece pensar que es Anypor alguna razón ...
Neil

0

Erlang (escript) - 200

main(X)->m(2,X).
m(63,_)->0;m(C,X)->try[F,G,I]=[c(0,C,Y)||Y<-X],I=F*G,io:fwrite("~p",[C])catch _:_->m(C+1,X)end.
c(A,B,[H|T])->D=H-if$A>H->$0;$a>H->29;0<1->87end,if D<B->c(A*B+D,B,T)end;c(A,_,_)->A.

Agregue dos nuevas líneas principales que deben estar presentes.

En legible:

#!/usr/bin/env escript

main(Args) -> test(2, Args).

test(63, _) -> 0;
test(Base, Args) ->
    try
        [Factor1, Factor2, Product] = [convert(0, Base, Arg) || Arg <- Args],
        Product = Factor1 * Factor2,
        io:fwrite("~p", [Base])
    catch _:_ ->
        test(Base + 1, Args)
    end.

convert(Accumulator, Base, [Head|Tail]) ->
    Digit = Head - if Head < $A -> $0;
                      Head < $a -> $A - 10 - 26;
                      true      -> $a - 10
                   end,
    if Digit < Base ->
        convert(Accumulator * Base + Digit, Base, Tail)
    end;
convert(Accumulator, _, _) -> Accumulator.

Invocación:

$ escript x.erl 6 9 42
13
$ escript -i x.erl a a 64
16
$ escript -i x.erl aA bB 36jk
41
$ escript -i x.erl 2 3 20
(no output)
$ escript -i x.erl 10 10 100
2

¿Esto se asegura de no devolver una base menor o igual a los dígitos más grandes?
Martin Ender

Sí, la if Digit < Base -> … endparte se encarga de eso. Si un ifbloque no tiene una rama verdadera, se lanza una excepción, que queda atrapada try … catch _:_ -> … end.
kay

0

Haskell 216 char (177?)

Intenté jugar al golf lo más posible. Si se cuentan las importaciones, entonces este es mi código más corto (216)

import Data.Char
import Data.List
m=maximum
j[]=0;j(x:_)=x
f=reverse.map(\x->ord x-48)
g[]_=0;g(m:n)x=m+x*g n x
main=do
l<-getLine
let k@[x,y,z]=words l
print$j[n|n<-[2..62],g(f x)n*g(f y)n==g(f z)n,n>(m.map(m.f)$k)]

Sin embargo, si las importaciones no se contabilizan, esta es mi mejor versión (177):

import Data.Char
import Data.List
import Control.Applicative
m=maximum
j[]=0;j(x:_)=x
f=reverse.map(\x->ord x-48)
g[]_=0;g(m:n)x=m+x*g n x
main=words<$>getLine>>= \k@[x,y,z]->print$j[n|n<-[2..62],g(f x)n*g(f y)n==g(f z)n,n>(m.map(m.f)$k)]

Esto trata cada número como un polinomio P (x) donde x es la base, con la condición de que ningún coeficiente sea mayor que x; Luego evalúo los polinomios sobre cada base posible, deteniéndome cuando alcanzo uno que satisface la igualdad P (x) * Q (x) = R (x). La regla 'la base es más grande que el dígito más grande' se aplica con el último guardia en la coincidencia de patrones, a saber n>(m.map(m.f)$k). Sé que los diferentes desafíos de golf y los diferentes creadores de desafíos tienen diferentes políticas con respecto a las importaciones frente al puntaje, así que tome el segundo con un grano de sal.


Las soluciones son en realidad 216 y 177 bytes / caracteres, respectivamente. Pero la segunda solución no es válida, porque las importaciones se cuentan a menos que el OP especifique explícitamente lo contrario, lo que no es el caso aquí, por lo que puedo decir.
nyuszika7h

0

Prólogo - 195 bytes

Básicamente la misma idea que mi respuesta Erlang:

:-use_module(library(main)).
main(A):-between(2,62,B),maplist(x(B),A,[F,G,P]),0is F*G-P,write(B).
c(I,B,Q,O):-Q=[H|T]->(H<65->D=48;H<97->D=29;D=87),H-D<B,c(I*B+H-D,B,T,O);O=I.
c(B)-->name,c(0,B).

En legible:

:- use_module(library(main)).

main(Args) :-
    between(2, 62, Base),
    maplist(convert(Base), Args, [Factor1, Factor2, Product]),
    0 is Factor1 * Factor2 - Product,
    write(Base).

convert(Accumulator, Base, List, Output) :-
    List = [Head|Tail] ->
        (   Head < 65 -> Offset = 48;
            Head < 97 -> Offset = 29;
                         Offset = 87),
        Head - Offset < Base,
        convert(Accumulator * Base + Head - Offset, Base, Tail, Output);
    Output = Accumulator.

convert(Base, Input, Output) :-
    name(Input, List),
    convert(0, Base, List, Output).

Invocación:

$ swipl -qg main x.pl 6 9 42
13
$ swipl -qg main x.pl aA bB 36jk
41
$ swipl -qg main x.pl 2 3 20
ERROR: Unknown message: goal_failed(main([2,3,20]))
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.