Trova la differenza BCD di un numero


20

Differenza BCD

Dato un numero intero n, convertilo in BCD ( decimale con codice binario ) sostituendo ogni cifra decimale con la sua rappresentazione binaria a 4 cifre

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

Quindi ruotare l'elenco di cifre binarie per trovare i numeri più grandi e più piccoli, rappresentabili da questo elenco senza altri riarrangiamenti.

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)

Converti questi numeri in decimali, trattando l'elenco di bit come binario normale e sottraendo il più piccolo dal più grande:

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

L'output è la differenza tra i numeri più grandi e quelli più piccoli trovati.

Casi test:

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

Risposte:


7

Wolfram Language (Mathematica) , 89 88 byte

Grazie a Jenny_mathy per aver salvato 1 byte.

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

Provalo online!

Questo è terribilmente inefficiente, perché genera n rotazioni del BCD di n , che è molto più di quanto abbiamo bisogno. Possiamo renderlo un po 'più efficiente salvando il risultato di Join@@in ke sostituendolo #con alla fine Length@k. Questo ci consente di generare un diagramma a dispersione abbastanza facilmente:

enter image description here

Sono davvero incuriosito dal contrasto della struttura locale e del caos generale.


Max@#-Min@#&salva un byte. giusto?
J42161217

@Jenny_mathy Sì, grazie! :)
Martin Ender,

1
Ho fatto questo dalle nostre soluzioni Max@#-Min@#&[#~FromDigits~2&/@Partition[s=Join@@(i=IntegerDigits)[i@#,2,4],Tr[1^s],1,1]]&89 byte ed efficiente. accidenti a quel byte!
J42161217

In realtà la trama è un patern ripetuto. Quelle "nuvole caotiche" si verificano ogni 10 ^ n (la trama "salta" e ne crea una nuova): 1-9,10-99,100-999... ecco alcuni zoom diversi: imgur.com/RXLMkco
J42161217

@Jenny_mathy certo, ma la struttura all'interno di questi intervalli appare molto caotica (con strutture solo su scale molto più piccole).
Martin Ender

6

Gelatina , 13 byte

Dd4d2FṙJ$ḄṢIS

Provalo online!

Come funziona

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.


4

PowerShell , 153 byte

$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]

Provalo online!

Stupide chiamate .NET lunghe per la conversione in / da binario si gonfiano davvero la lunghezza qui. ;-)

Prendiamo l'input come $args, lo avvolgiamo in una stringa, quindi lo charlanciamo come un array. Passiamo su ogni cifra, convertinserendo la cifra toStringin base 2(ovvero trasformando la cifra in un numero binario), quindi .padLeftper renderla un numero binario di quattro cifre. Quell'array di stringhe risultante viene quindi -joininserito in una singola stringa e ri-cast come un chararray prima di essere salvato in$b .

Successivamente, eseguiamo il loop over $b, il che si assicura che siamo in loop abbastanza volte per tenere conto di ogni rotazione. Ad ogni iterazione, togliamo il primo carattere $xe i personaggi rimanenti $ynell'uso di assegnazioni multiple. Quindi, li uniamo di nuovo insieme $b=$y+$xper spostare il primo elemento alla fine, cioè ruotando efficacemente l'array di uno. Questo è -joinEd in una stringa, che viene utilizzata come ingresso alla convertchiamata per trasformare la stringa dalla base binaria 2in un Int64. Abbiamo quindi sorttutti quei numeri risultanti e li memorizziamo in $c. Infine, prendiamo il più grande [-1]e sottraggiamo il più piccolo [0]. Rimane in cantiere e l'output è implicito.


4

Ohm v2 , 15 byte

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

Provalo online!

Spiegazione:

€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

4

JavaScript (ES6), 118 100 99 byte

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>

Modifica: salvato 11 byte grazie a @RickHitchcock. Salvato 1 byte grazie a @ETHproductions. Spiegazione: Il 0x1prefisso fa sì che l'input venga replicato come un numero esadecimale, il cui binario è uguale al BCD del numero originale con un prefisso 1 (penso che questo sia più golfoso di qualsiasi altro modo di riempire con un multiplo di 4 cifre) . Escludendo il prefisso, che viene modificato da 1 a 0, la stringa risultante viene quindi ruotata in ciascuna posizione possibile e convertita da binario a decimale. Infine vengono sottratti il ​​massimo e il minimo.


1
@RickHitchcock Avvolgi la stringa in doppi backtick ... a meno che tu non voglia scrivere qualcosa come .join`` nel qual caso hai bisogno di triple backtick ecc.
Neil

Buona idea usare esadecimali. Salva 11 byte in questo modo: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 Grazie, mi ha aiutato ... a tagliare ... altri 7 byte rimuovendo sliceanche un altro !
Neil,

1
Il m=>Math[m]trucco è fantastico. Forse cambiare (+`0x1${n}`)a ('0x1'+n-0)o simili?
ETHproductions



3

Buccia , 18 byte

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

Provalo online!

Dovrebbe esserci un modo più breve per convertire una cifra nella sua rappresentazione binaria a 4 bit ...

Spiegazione

§-▼▲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

3

APL (Dyalog) , 31 byte

Corpo del programma completo. Richiede il numero da STDIN. Stampa il risultato su STDOUT.

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

Provalo online!

 richiede una riga di testo da STDIN

⍎¨ eseguire (valutare) ciascuno (carattere)

(...)⊤  codificare (anti-base) nel seguente sistema numerico:

4/2 quattro bit binari

 trasporre

, corvo (appiattire)

b← conservare in b(per b inary)

 allegare (in modo che utilizzeremo l'intero elenco per ogni rotazione)

(...)⌽¨  ruota (a sinistra) di ciascuno dei seguenti importi:

≢b lunghezza di b

io conoscenza

2⊥¨ decodifica ciascuno dalla base-2.

(...)  applica la seguente funzione tacita

⌈/ il massimo (riduzione)

- meno

⌊/ il minimo (riduzione)


potresti facilmente addestrare questo bit: (⍳≢b) ⌽¨⊂b ←
ngn

o ancora meglio - usa (≢, /, ⍨) invece dell'ovvio (⍳∘≢⌽¨⊂)
ngn




2

Mathematica, 110 99 byte

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


Provalo online!


2

Python 3, 141 byte

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)

Provalo online


2

Retina , 96 89 byte

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

_

Provalo online! Un po 'lento, quindi il collegamento include solo un piccolo test case. Modifica: salvato 7 byte grazie a @MartinEnder. Spiegazione:

.
@@@$&

Prefisso tre @s per ogni cifra. (Rappresentano la 0s del BCD, ma sono più golfisti.)

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

Modificare le @s in _s (che rappresentano le 1s del BCD) ove appropriato.

T`E`@
\d
_

Correggi l'ultima cifra del BCD.

.
$&$'$`¶

Genera tutte le rotazioni.

O`

Ordinali in ordine crescente.

_
@_
+`_@
@__

Converti in unario.

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

_

Sottrai il primo dall'ultimo numero, ignorando i numeri intermedi e convertilo in decimale.


Non è necessario utilizzare %per la conversione da binario a unario e puoi salvare qualche byte in più utilizzando altri caratteri rispetto a 0e 1per binario: tio.run/##K0otycxL/…
Martin Ender

@MartinEnder Oh, penso che risalisse a quando stavo provando e non riuscivo a usare una delle tue routine di conversione binaria ...
Neil

2

Haskell , 130 byte

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]

Provalo online!

Spiegazione / Non golf

Dato che useremo foldl1((+).(2*))per convertire da binario a decimale, potremmo anche non usare maximume minimumpiuttosto foldl1 max(o lo stesso con minrispettivamente) e usare un short r = foldr1.

Ora, definiamo un operatore f#xche converte xin BCD, genera tutte le rotazioni, riducile usando fe convertendolo in decimale:

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

Ora si tratta solo di usare questo operatore una volta con maxe una volta con mine sottrarre i loro risultati:

f x = max#x - min#x

2

PHP, 156 153 byte

<?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);

Provalo online!


2

Japt -x , 20 byte

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

Provalo online!

Immettere come una matrice di cifre.

Spiegazione:

®¤                      #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

1
È possibile utilizzare il -xflag per salvare 2 byte.
Oliver,



1

J, 43 byte

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

Provalo online!

A volte lo stile tacito rende le cose difficili. Ma c'è probabilmente un modo per farlo in modo tacito che è molto più conciso di così. Penso di ricordare un modo migliore per dividere un numero in cifre diverse da"."0@": ma non riesco a ricordarmelo ...

Spiegazione

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

L'anticipo e la rimozione di 8 serve a garantire la presenza del giusto numero di zeri (J ridisegnerà i suoi array in modo che abbiano la dimensione del loro elemento di lunghezza massima e 8 sia binario di 4 cifre in modo da essere utilizzato).


1

APL (NARS), 34 caratteri, 68 byte

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

qualche piccolo test:

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

1

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

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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.