Encontre a diferença BCD de um número

20

Diferença BCD

Dado um número inteiro n, converta-o para BCD ( decimal com código binário ) substituindo cada dígito decimal pela sua representação binária de 4 dígitos

 234 -> 0 0 1 0 0 0 1 1 0 1 0 0

Em seguida, gire a lista de dígitos binários para encontrar os números maiores e menores, representáveis ​​por essa lista sem outros rearranjos.

max: 1 1 0 1 0 0 0 0 1 0 0 0  (the entire list rotated left 6 times)
min: 0 0 0 0 1 0 0 0 1 1 0 1 (the entire list rotated right 2 times)

Converta esses números de volta para decimal, tratando a lista de bits como binário regular e subtraia o menor do maior:

1 1 0 1 0 0 0 0 1 0 0 0 -> 3336
0 0 0 0 1 0 0 0 1 1 0 1 -> 141

3336 - 141 -> 3195

A saída é a diferença dos números maiores e menores encontrados.

Casos de teste:

234 -> 3195
1234 -> 52155
12 -> 135
975831 -> 14996295
4390742 -> 235954919
9752348061 -> 1002931578825
Galen Ivanov
fonte

Respostas:

7

Wolfram Language (Mathematica) , 89 88 bytes

Obrigado a Jenny_mathy por economizar 1 byte.

i=IntegerDigits;Max@#-Min@#&[#~FromDigits~2&/@NestList[RotateRight,Join@@i[i@#,2,4],#]]&

Experimente online!

Isso é terrivelmente ineficiente, porque gera n rotações do BCD de n , que é muito mais do que precisamos. Podemos tornar isso um pouco mais eficiente salvando o resultado do Join@@in ke substituindo o #no final por Length@k. Isso nos permite gerar um gráfico de dispersão facilmente:

insira a descrição da imagem aqui

Estou realmente intrigado com o contraste da estrutura local e do caos geral.

Martin Ender
fonte
Max@#-Min@#&salva um byte. direita?
J42161217
@Jenny_mathy Yeah, obrigado! :)
Martin Ender
1
Eu fiz isso de nossas soluções Max@#-Min@#&[#~FromDigits~2&/@Partition[s=Join@@(i=IntegerDigits)[i@#,2,4],Tr[1^s],1,1]]&89 bytes E eficiente. caramba esse byte!
J42161217
Na verdade, o enredo é um patern.Those repetida "nuvens caóticas" acontecem a cada 10 ^ n (o enredo "salta" e criar um novo): 1-9,10-99,100-999... aqui estão algumas zooms diferentes: imgur.com/RXLMkco
J42161217
@ Jenny_mathy com certeza, mas a estrutura dentro desses intervalos parece muito caótica (com estruturas apenas em escalas muito menores).
Martin Ender
6

Gelatina , 13 bytes

Dd4d2FṙJ$ḄṢIS

Experimente online!

Como funciona

Dd4d2FṙJ$ḄṢIS  Main link. Argument: n

D              Decimal; convert n to base 10 (digit array).
 d4            Divmod 4; map each digit d to [d/4, d%4].
   d2          Divmod 2; map each [d/4, d%4] to [[d/8, d/4%2], [d%4/2, d%2]].
     F         Flatten the resulting 3D binary array.
      ṙJ$      Take all possible rotations.
         Ḅ     Convert each rotation from binary to integer.
          Ṣ    Sort the resulting integer array.
           I   Take the forward differences.
            S  Take the sum.
Dennis
fonte
4

PowerShell , 153 bytes

$b=[char[]]-join([char[]]"$args"|%{[convert]::toString(+"$_",2).PadLeft(4,'0')})
($c=$b|%{$x,$y=$b;[convert]::ToInt64(-join($b=$y+$x),2)}|sort)[-1]-$c[0]

Experimente online!

Chamadas estúpidas do .NET para converter de / para binários realmente aumentam o tamanho aqui. ;-)

Tomamos a entrada como $args, envolvemos em uma string e a charlançamos como um array. Passamos um loop sobre cada dígito, convertdigitando o dígito toStringna base 2(ou seja, transformando o dígito em um número binário) e, em seguida, transformando-o em um número binário de .padLeftquatro dígitos. Essa matriz resultante de seqüências de caracteres é -joineditada em uma única sequência e lançada novamente como uma charmatriz antes de ser salva $b.

Em seguida, fazemos o loop $b, o que garante um tempo suficiente para dar conta de cada rotação. A cada iteração, destacamos o primeiro caractere $xe os demais caracteres $yusando várias atribuições. Em seguida, os juntamos novamente $b=$y+$xpara mover o primeiro elemento até o fim, ou seja, girando efetivamente o array por um. Isso é -joined em uma string, que é usada como entrada para a convertchamada para transformar a string da base binária 2em uma Int64. Em seguida, sorttodos esses números resultantes e os armazenamos $c. Finalmente, pegamos o maior [-1]e subtraímos o menor [0]. Isso é deixado no pipeline e a produção está implícita.

AdmBorkBork
fonte
4

Ohm v2 , 15 bytes

€b4Ü. 0\;Jγó↕]a

Experimente online!

Explicação:

€b4Ü. 0\;Jγó↕]a  Main wire, arguments: a (integer)

€       ;        Map the following over each digit of a...
 b                 Convert to binary
  4Ü               Right-justify w/ spaces to length 4
    . 0\           Replace all spaces with zeroes
         J       Join together binary digits
          γó     Get all possible rotations and convert back to decimal
            ↕    Find the minimum *and* maximum rotation
             ]a  Flatten onto stack and get the absolute difference
Nick Clifford
fonte
4

JavaScript (ES6), 118 100 99 bytes

f=
n=>(g=m=>Math[m](...[...s=(`0x1`+n-0).toString(2)].map(_=>`0b${s=0+s.slice(2)+s[1]}`)))`max`-g`min`
<input type=number min=0 oninput=o.textContent=f(this.value)><pre id=o>

Editar: salvou 11 bytes graças a @RickHitchcock. Economizou 1 byte graças a @ETHproductions. Explicação: O 0x1prefixo faz com que a entrada seja reparada como um número hexadecimal, cujo binário é o mesmo que o BCD do número original com um prefixo 1 (acho que isso é mais golfista do que qualquer outra maneira de preencher com vários dígitos de 4) . Excluindo o prefixo, que é alterado de 1 para 0, a sequência resultante é então girada em cada posição possível e convertida de binário de volta para decimal. Finalmente, o máximo e o mínimo são subtraídos.

Neil
fonte
1
@RickHitchcock Enrole a corda em backticks duplas ... a menos que você quer escrever algo como .join`` no caso em que você precisa triplicar backticks etc.
Neil
Boa ideia usar hexadecimal. Salve 11 bytes como este:n=>(g=m=>Math[m](...[...s=(+`0x1${n}`).toString(2).slice(1)]‌​.map(_=>`0b${s=s.sli‌​ce(1)+s[0]}`)))`max`‌​-g`min`
Rick Hitchcock
1
@ RickHitchcock Obrigado, isso me ajudou ... cortar ... outros 7 bytes removendo outro slicetambém!
22417 Neil
1
O m=>Math[m]truque é ótimo. Talvez mude (+`0x1${n}`)para ('0x1'+n-0)ou similar?
ETHproductions
3

Python 2 , 115 113 bytes

  • Salvou alguns bytes graças a ovs .
  • Economizou dois bytes graças ao Sr. Xcoder .
b="".join(format(int(n),"04b")for n in`input()`)
b=[int(b[s:]+b[:s],2)for s in range(len(b))]
print max(b)-min(b)

Experimente online!

Jonathan Frech
fonte
3

Casca , 18 bytes

§-▼▲mḋUMṙNṁȯtḋ+16d

Experimente online!

Deve haver uma maneira mais curta de converter um dígito em sua representação binária de 4 bits ...

Explicação

§-▼▲mḋUMṙNṁȯtḋ+16d
                 d    Get the list of digits of the input
          ṁȯ          For each digit...
              +16      add 16
             ḋ         convert to binary
            t          drop the first digit
       MṙN            Rotate the list by all possible (infinite) numbers
      U               Get all rotations before the first duplicated one
    mḋ                Convert each rotation from binary to int
§-▼▲                  Subtract the minimum from the maximum value
Leo
fonte
3

APL (Dyalog) , 31 bytes

Corpo do programa completo. Solicita o número de STDIN. Imprime o resultado em STDOUT.

(⌈/-⌊/)2⊥¨(⍳≢b)⌽¨⊂b←,⍉(4/2)⊤⍎¨⍞

Experimente online!

 solicitar linha de texto de STDIN

⍎¨ executar (avaliar) cada (caractere)

()⊤ Codifique (anti-base) no seguinte sistema numérico:

4/2 quatro bits binários

 transpor

, ravel (achatar)

b← armazenar em b(por b inário)

 coloque (para que possamos usar toda a lista para cada rotação)

()⌽¨ Gire (esquerda) de cada uma das seguintes quantidades:

≢b Comprimento de b

i ndices de que

2⊥¨ decodifique cada um da base-2.

() Aplique a seguinte função tácita a esse

⌈/ o máximo (redução)

- menos

⌊/ o min (-redução)

Adão
fonte
você poderia facilmente treinar este bit: (⍳≢b) ←¨⊂b ←
ngn
ou ainda melhor - uso (≢, /, ⍨) em vez do óbvio (⍳∘≢⌽¨⊂)
NGN
2

Ruby , 96 91 bytes

->n{r=""
n.digits.map{|d|r="%04b"%d+r}
s=r.chars.map{(r=r[1..-1]+r[0]).to_i 2}
s.max-s.min}

Experimente online!

  • Economizou 5 bytes graças ao displayname
Restabelecer Monica - notmaynard
fonte
-> n {r = "" n.dígitos.map {| d | r = "% 04b"% d + r} s = r.chars.map {(r = r [1 ..- 1] + r [ 0]). To_i 2} s.max-s.min} deve ter 91 bytes
displayname
@displayname Ha, sim, você está certo. Obrigado
Reinstate Monica - notmaynard 15/17
2

Mathematica, 110 99 bytes

Max@#-Min@#&[#~FromDigits~2&/@Partition[s=Join@@Tuples[{0,1},4][[IntegerDigits@#+1]],Tr[1^s],1,1]]&


Experimente online!

J42161217
fonte
2

Python 3, 141 bytes

def f(a):a=''.join([format(int(i),'#010b')[-4:]for i in str(a)]);b=[int(''.join(a[-i:]+a[:-i]),2)for i in range(len(a))];return max(b)-min(b)

Experimente online

sonrad10
fonte
2

Retina , 96 89 bytes

.
@@@$&
@(?=@@[89]|@[4-7]|[2367])
_
T`E`@
\d
_
.
$&$'$`¶
O`
_
@_
+`_@
@__
s`(_+).*\W\1

_

Experimente online! Um pouco lento, portanto, o link inclui apenas um pequeno caso de teste. Editar: salvou 7 bytes graças a @MartinEnder. Explicação:

.
@@@$&

Prefixe três @s para cada dígito. (Eles representam os 0s do BCD, mas são mais golfistas.)

@(?=@@[89]|@[4-7]|[2367])
_

Altere os @s para _s (representando os 1s do BCD), onde apropriado.

T`E`@
\d
_

Corrija o último dígito do BCD.

.
$&$'$`¶

Gere todas as rotações.

O`

Classifique-os em ordem crescente.

_
@_
+`_@
@__

Converta-os em unários.

s`(_+).*\W\1

_

Subtraia o primeiro do último número, ignorando os números intermediários e converta para decimal.

Neil
fonte
Não há necessidade de usar %para o binário para conversão unário e você pode economizar um pouco mais bytes usando outros personagens do que 0e 1de binário: tio.run/##K0otycxL/...
Martin Ender
@MartinEnder Oh, eu acho que datado de quando eu estava tentando e falhando em usar uma das suas rotinas de conversão binários ...
Neil
2

Haskell , 130 bytes

r=foldl1
f x=max#x-min#x
f#x|s<-show x=r((+).(2*)).r f.take(sum$4<$s).iterate(drop<>take$1)$do d<-s;mapM(pure[0,1])[1..4]!!read[d]

Experimente online!

Explicação / Ungolfed

Como vamos usar foldl1((+).(2*))para converter de binário em decimal, é melhor não usarmos maximume, em minimumvez disso foldl1 max(ou o mesmo com, minrespectivamente) e usar um pequeno r = foldr1.

Agora, vamos definir um operador f#xque converte xem BCD, gera todas as rotações, reduza-as usando fe converte-as em decimal:

f # xs
  | s <- show xs
  = foldr1 ((+).(2*))                             -- convert from binary to decimal
  . foldr1 f                                      -- reduce by either max or min
  . take (4 * length s)                           -- only keep 4*length s (ie. all "distinct" rotations)
  . iterate (drop<>take $ 1)                      -- generate infinite list of rotations
  $ do d<-s; mapM (pure[0,1]) [1..4] !! read [d]  -- convert to BCD

Agora é apenas uma questão de usar esse operador uma vez maxe uma vez com mine subtrair seus resultados:

f x = max#x - min#x
ბიმო
fonte
2

PHP, 156 153 bytes

<?foreach(str_split($argv[1])as$n)$s.=str_pad(decbin($n),4,0,0);for(;$i<$a=strlen($s);)$r[]=bindec(substr($s,$i).substr($s,0,$i++));echo max($r)-min($r);

Experimente online!

Jo.
fonte
2

Japonês -x , 20 bytes

®¤ùT4쬣ZéY ì2Ãn äa

Experimente online!

Entrada como uma matriz de dígitos.

Explicação:

®¤                      #Map each digit to base 2
  ùT4Ã                  #Pad each one to 4 places
      ¬                 #Join them to a single binary string
       ¬                #Split them to an array of single characters
        £      Ã        #For each index Y in that array:
         ZéY            # Get the array rotated Y times
             ì2         # Convert the array from binary to decimal
                n       #Sort the results
                  äa    #Get the absolute difference between each element
                        #Implicitly output the sum
Kamil Drakari
fonte
1
Você pode usar o -xsinalizador para salvar 2 bytes.
23418 Oliver Oliver
1
20 bytes .
21418 Oliver
1

J, 43 bytes

3 :'(>./-<./)#.(i.@#|."0 1]),}.#:8,"."0":y'

Experimente online!

Às vezes, o estilo tácito dificulta as coisas. Mas provavelmente existe uma maneira de fazê-lo com um estilo tácito que é muito mais conciso do que isso. Acho que me lembro de uma maneira melhor de dividir um número em outros dígitos, "."0@":mas não consigo me lembrar dele ...

Explicação

3 :'(>./-<./)#.(i.@#|."0 1]),}.#:8,"."0":y'
                                         y  the input (integer)
                                       ":   convert to string
                                   "."0     evaluate each char (split to digits)
                                 8,         prepend 8
                               #:           debase 2
                             }.             behead (remove the 8)
                            ,               ravel (flatten)
               (i.@#|."0 1])                create a list of rotations
                    |.    ]                   rotate the list
                      "0 1                    for each number on the left
                i.@#                          range 0 ... length - 1
             #.                             convert rotations back to base 10
    (>./-<./)                               max minus min

O pré-anexo e a remoção 8 são para garantir que o número certo de zeros esteja presente (J remodelará suas matrizes para que sejam do tamanho do elemento de comprimento máximo e 8 é de 4 dígitos em binário, para que seja usado).

Cole
fonte
1

APL (NARS), 34 caracteres, 68 bytes

{(⌈/-⌊/)2⊥¨{⍵⌽a}¨⍳≢a←∊⍉(4⍴2)⊤⍎¨⍕⍵}

algum pequeno teste:

  h←{(⌈/-⌊/)2⊥¨{⍵⌽a}¨⍳≢a←∊⍉(4⍴2)⊤⍎¨⍕⍵}
  h 9752348061
1002931578825
  h 0
0
RosLuP
fonte
1

Perl 5 , 97 91 89 + 2 ( -F) = 99 93 91 bytes

$a=sprintf"%04b"x@F,@F;@r=sort{$b<=>$a}map{oct"0b".($a=(chop$a).$a)}(@F)x4;say$r[0]-pop@r

Experimente online!

Xcali
fonte