Determinar a base onde uma dada equação é verdadeira


22

Dados três números inteiros, determine a base mais baixa possível para os dois primeiros inteiros se multiplicarem no terceiro. Se você pensa na resposta à questão final da vida, do universo e de tudo, 6 * 9 == 42, é verdadeira na Base 13.

As entradas podem incluir qualquer número cujos dígitos usem os caracteres 0-9, az e AZ, onde aé igual a 10 na Base 10 e Zé 61 na Base 10.

As entradas devem ser inseridas da maneira que desejar (exceto para codificação), e você pode escrever uma função individual ou um programa inteiro.

A base máxima que deve ser considerada é a Base 62 e a base mínima é a Base 2.

Você pode assumir que os dois primeiros valores são menores que o terceiro. Você também pode concluir que a base mínima é uma maior que o dígito / caractere mais alto das entradas (por exemplo, se as entradas forem 3 1a 55, a base mínima seria a Base 11, porque aé o dígito mais alto).

Se não houver essa base, retorne um valor de lixo eletrônico de sua escolha.

Isso é código de golfe, então o código mais curto vence.

Casos de teste

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

Eu acho que o STDIN provavelmente seria melhor, e qualquer um seria bom.
erdekhayser

@ MartinBüttner Então, devo apenas permitir a entrada de qualquer forma?
erdekhayser

1
Como ponto de esclarecimento, o que deve ser feito se várias bases forem válidas, como o seu último exemplo (que foi removido agora - era 10 * 10 = 100), onde também é válido na base 10 e na verdade qualquer outra base que você queira mencionar ...
Chris

1
@ Kay Se eu definir o sistema posicional na base bde uma maneira geral, como a_0 b^0 + a_1 b^1 + a_2 b^2 + ...(onde a_0é o dígito menos significativo) do que a base 1, definitivamente faz sentido. Além disso, a conclusão do OP também incluiria a base 1 na pesquisa, se o maior dígito atual for 0. #
919 Martin Ender

2
Sobre a base 1, unário é um sistema numérico. en.m.wikipedia.org/wiki/Unary_numeral_system
erdekhayser 27/10

Respostas:


3

CJam, 52 51 48 bytes

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

Teste aqui. O testador online não suporta entrada via ARGV. A alternativa mais próxima é colocar a entrada como 6 9 42em STDIN e usar:

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

Imprime -1se nenhuma base válida até 62 puder ser encontrada.

Muito obrigado a Peter pelo código de análise de dígitos!

Corrigi muitos problemas que adicionavam 14 bytes à contagem. A explicação a seguir ainda é para o meu envio original, e vou atualizá-lo amanhã.

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.";

O índice é impresso automaticamente no final do programa.


No GS, os dígitos podem ser analisados ​​como 32base~\[-16.35 9]=+. Eu sei que o CJam tem uma conversão base mais curta.
Peter Taylor

7

APL (Dyalog Unicode) , SBCS de 30 bytes

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

Experimente online!

Obrigado a Adám pela ajuda.

Explicação:

⊢{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 uma função auxiliar,, Inpara receber a entrada em um formato mais palatável. Caso contrário, a entrada recebe uma matriz de 3 colunas.

'3 9 42' daria, por exemplo (leia de cima para baixo e da esquerda para a direita):

0 0 4
3 9 2

E para 'aA bB 36jk'(o mesmo aqui. aÉ 10, bé 11, Aé 36, etc)

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

2

Python 2-197 213

Que monstro ... (comparado ao 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]

Infelizmente int, a conversão de base só pode lidar com bases de até 36. Portanto, eu precisava implementá-la sozinha. (Veja esta maravilhosa solução .)


Isso garante que você não retorne uma base menor ou igual aos dígitos maiores?
Martin Ender

@ MartinBüttner: Não tenho certeza. Pelo menos não explicitamente. Você tem um caso de teste em que isso é um problema? (Na verdade, gerar casos de teste deve ser tomado cuidado de pelo OP ...)
Falko

Tente 2 * 3 = 20, que possui a base 3 em um caso de erro. 3 não é um dígito em um sistema de numeração ternária.
kay

2

CJam, 53 bytes

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

Toma as três entradas do STDIN como

6 9 42

Imprime 0se o produto em qualquer base não for possível

Vai tentar jogar mais.

Experimente aqui


1

JavaScript (E6) 129 139

Tente recursivamente todas as bases de 2 a 62, retornando -1 se nenhum valor estiver correto.
A função parseInt do JavaScript funciona com base até 36, portanto, é necessária uma pequena ajuda para bases maiores.
Cuidado, os parâmetros x, y, z são cadeias de caracteres, não números.
É mais difícil do que parece. Agradecemos a Martin por apontar um bug básico na primeira versão.

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 golfe

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

Teste no console do FireFox / FireBug.
O teste tenta 1000 números com bases diferentes (até 36, não 62). Vale a pena notar que a base encontrada pode estar correta, mas menor que a base que gerou o caso de teste.

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, os parâmetros são strings (já que os valores possíveis são algo como aA bB 36jk ...). Esclarecido na resposta.
Edc65 # 28/14

Oh, certo, isso faz sentido.
Martin Ender

1

Carvão , 28 bytes

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

Experimente online! Link é a versão detalhada do código. Saídas Nonese nenhuma base válida puder ser encontrada. Explicação:

         θ                      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

É possível ter um programa TIO que usa o código real que você postou?
mbomb007 6/03

@ mbomb007 Você pode experimentá-lo online! mas o gerador AST parece achar que é Anypor algum motivo ...
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.

Adicione duas novas linhas principais que devem estar presentes.

Em legível:

#!/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.

Invocação:

$ 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

Isso garante que você não retorne uma base menor ou igual aos dígitos maiores?
Martin Ender

Sim, a if Digit < Base -> … endparte cuida disso. Se um ifbloco não tiver ramificação verdadeira, uma exceção será lançada, a qual será capturada try … catch _:_ -> … end.
kay

0

Haskell 216 char (177?)

Tentei jogar isso o máximo possível. Se as importações forem contadas, esse é o meu código mais curto (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)]

No entanto, se as importações não foram contadas, esta é minha melhor versão (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)]

Isso trata cada número como um polinômio P (x) onde x é a base, desde que nenhum coeficiente seja maior que x; Em seguida, avalio os polinômios sobre cada base possível, parando quando chego a uma que satisfaça a igualdade P (x) * Q (x) = R (x). A regra 'base é maior que o dígito maior' é aplicada com o último protetor na correspondência de padrão, a sabern>(m.map(m.f)$k) . Sei que diferentes desafios no golfe e diferentes formadores de desafio têm políticas diferentes em relação às importações em relação à pontuação; portanto, leve o segundo com um pouco de sal.


As soluções são na verdade 216 e 177 bytes / caracteres, respectivamente. Mas a segunda solução é inválida, porque as importações são contadas, a menos que o OP especifique explicitamente o contrário, o que não é o caso aqui, até onde eu sei.
nyuszika7h

0

Prolog - 195 bytes

Basicamente, a mesma idéia da minha resposta 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).

Em legível:

:- 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).

Invocação:

$ 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]))
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.