Найти разность чисел BCD

20

BCD разница

Получив целое число n, преобразуйте его в BCD ( двоично-десятичное десятичное число ), заменив каждую десятичную цифру ее четырехзначным двоичным представлением

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

Затем поверните список двоичных цифр, чтобы найти самые большие и самые маленькие числа, представляемые этим списком без других перестановок.

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)

Преобразуйте эти числа обратно в десятичные, рассматривая список битов как обычный двоичный файл и вычитая наименьшее из наибольшего:

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

Выходными данными является разница самых больших и самых маленьких найденных чисел.

Тестовые случаи:

234 -> 3195
1234 -> 52155
12 -> 135
975831 -> 14996295
4390742 -> 235954919
9752348061 -> 1002931578825
Гален Иванов
источник

Ответы:

7

Wolfram Language (Mathematica) , 89 88 байт

Спасибо Jenny_mathy за сохранение 1 байта.

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

Попробуйте онлайн!

Это ужасно неэффективно, потому что оно генерирует n вращений BCD из n , что намного больше, чем нам нужно. Мы можем сделать это немного более эффективным, сохранив результат Join@@in kи заменив #в конце на Length@k. Это позволяет нам легко создать диаграмму рассеяния:

введите описание изображения здесь

Я действительно заинтригован контрастом местной структуры и общего хаоса.

Мартин Эндер
источник
Max@#-Min@#&сохраняет байт. право?
J42161217
@Jenny_mathy Да, спасибо! :)
Мартин Эндер
1
Я сделал это из наших решений Max@#-Min@#&[#~FromDigits~2&/@Partition[s=Join@@(i=IntegerDigits)[i@#,2,4],Tr[1^s],1,1]]&89 байтов и эффективно. черт побери!
J42161217
На самом деле сюжет повторяется. Эти «хаотические облака» случаются каждые 10 ^ n (сюжет «прыгает» и создает новое): 1-9,10-99,100-999... вот несколько разных масштабов
J42161217
@Jenny_mathy конечно, но структура в этих интервалах выглядит очень хаотично (со структурами только в гораздо меньших масштабах).
Мартин Эндер
6

Желе , 13 байт

Dd4d2FṙJ$ḄṢIS

Попробуйте онлайн!

Как это устроено

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 байта

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

Попробуйте онлайн!

Глупые длинные .NET-вызовы для преобразования в / из двоичного кода действительно увеличивают длину здесь. ;-)

Мы принимаем входные данные как $args, заключаем их в строку, а затем charприводим их как -array. Мы перебираем каждую convertцифруtoString в базе 2(т.е. превращая цифру в двоичное число), .padLeftчтобы затем сделать ее четырехзначным двоичным числом. Этот результирующий массив строк затем -joinпреобразуется в одну строку и charпередается в виде -array перед сохранением в $b.

Затем мы повторяем цикл $b, который просто гарантирует, что мы зациклимся достаточно раз, чтобы учесть каждый поворот. На каждой итерации мы удаляем первый символ, $xа остальные символы - $yиспользуя множественное присваивание. Затем мы объединяем их вместе, $b=$y+$xчтобы переместить первый элемент в конец, т. Е. Эффективно вращая массив на единицу. Это -joinпревращается в строку, которая используется в качестве входных данных для convertвызова, чтобы превратить строку из двоичной базы 2в Int64. Затем мы sortвсе эти результирующие числа и сохранить их в $c. Наконец, мы берем самое большое [-1]и вычитаем самое маленькое [0]. Это осталось на конвейере и вывод неявный.

AdmBorkBork
источник
4

Ом v2 , 15 байт

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

Попробуйте онлайн!

Объяснение:

€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 байт

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>

Изменить: Сохранено 11 байтов благодаря @RickHitchcock. Сохранено 1 байт благодаря @ETHproductions. Объяснение: 0x1Префикс приводит к тому, что ввод переопределяется как шестнадцатеричное число, двоичное число которого совпадает с BCD исходного числа с префиксом 1 (я думаю, что это лучше, чем любой другой способ дополнения до числа, кратного 4 цифрам) , Исключая префикс, который изменяется с 1 на 0, результирующая строка затем поворачивается в каждой возможной позиции и преобразуется из двоичного обратно в десятичное. Наконец максимум и минимум вычитаются.

Нил
источник
1
@RickHitchcock Оберните строку в двойные обратные кавычки ... если вы не хотите написать что-то вроде того, .join`` в этом случае вам нужны тройные обратные кавычки и т. Д.
Нейл
Хорошая идея использовать шестнадцатеричное. Сохранить 11 байтов, как это:n=>(g=m=>Math[m](...[...s=(+`0x1${n}`).toString(2).slice(1)]‌​.map(_=>`0b${s=s.sli‌​ce(1)+s[0]}`)))`max`‌​-g`min`
Рик Хичкок
1
@RickHitchcock Спасибо, это помогло мне ... отрезать ... еще 7 байтов, удалив еще один slice!
Нил
1
m=>Math[m]Трюк велик. Возможно изменить (+`0x1${n}`)к ('0x1'+n-0)или подобное?
ETHproductions
3

Шелуха , 18 байт

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

Попробуйте онлайн!

Должен быть более короткий способ преобразования цифры в ее 4-битное двоичное представление ...

объяснение

§-▼▲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 байт

Полное тело программы. Запрашивает номер из STDIN. Печать результатов в STDOUT.

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

Попробуйте онлайн!

 запросить строку текста из STDIN

⍎¨ выполнить (оценить) каждого (персонажа)

()⊤ Кодировать (антибазис) в следующей системе счисления:

4/2 четыре двоичных разряда

 транспонирования

, Равель (сплющить)

b← хранить в b(для б )

 заключить (чтобы мы использовали весь этот список для каждого поворота)

(... )⌽¨ повернуть (влево) на каждую из следующих величин:

≢b длина b

я думаю об этом

2⊥¨ расшифровать каждый из базы-2.

(... ) применить следующую молчаливую функцию к этому

⌈/ макс (-редукция)

- минус

⌊/ мин (-снижение)

Адам
источник
Вы можете легко обучить этот бит: (⍳≢b) ←b ←
ngn
или даже лучше - используйте (≢, /, ⍨) вместо очевидного (⍳∘≢⌽¨⊂)
нгн
2

Рубин , 96 91 байт

->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}

Попробуйте онлайн!

  • Сохранено 5 байтов благодаря отображаемому имени
Восстановить Монику - нотайнард
источник
-> 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} должно быть 91 байт
DisplayName
@displayname Ха, да, ты прав. Спасибо
Восстановите Монику - Нотмайнард
2

Сетчатка , 96- 89 байт

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

_

Попробуйте онлайн! Несколько медленный, поэтому ссылка включает в себя только небольшой тестовый пример. Редактировать: 7 байтов сохранено благодаря @MartinEnder. Объяснение:

.
@@@$&

Префикс три @с каждой цифрой. (Они представляют собой 0BCD, но являются игроками в гольф.)

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

Замените @s на _s (представляющий 1s BCD), где это необходимо.

T`E`@
\d
_

Исправьте последнюю цифру BCD.

.
$&$'$`¶

Генерация всех поворотов.

O`

Сортируйте их в порядке возрастания.

_
@_
+`_@
@__

Перевести их в одинарные.

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

_

Вычтите первое из последнего числа, игнорируя промежуточные числа, и преобразуйте в десятичное число.

Нил
источник
Нет необходимости использовать %для двоичного преобразования в унарное, и вы можете сохранить еще несколько байтов, используя другие символы, чем 0и 1для двоичного: tio.run/##K0otycxL/…
Martin Ender
@MartinEnder О, я думаю, это датировано тем, когда я пытался и не смог использовать одну из ваших программ двоичного преобразования ...
Нил
2

Haskell , 130 байт

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]

Попробуйте онлайн!

Объяснение / Ungolfed

Так как мы собираемся использовать foldl1((+).(2*)) для преобразования из двоичной системы в десятичную, мы могли бы также использовать maximumи minimumа foldl1 max(или же с minсоответственно) и использовать короткийr = foldr1 .

Теперь давайте определим оператор f#x который конвертирует xв BCD, генерирует все вращения, сокращает их, используя fи преобразует в десятичную форму:

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

Теперь это только вопрос использования этого оператора один раз maxи один раз с minвычитанием их результатов:

f x = max#x - min#x
ბიმო
источник
2

Japt -x , 20 байт

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

Попробуйте онлайн!

Ввод в виде массива цифр.

Объяснение:

®¤                      #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
Вы можете использовать -xфлаг, чтобы сохранить 2 байта.
Оливер
1
20 байтов .
Оливер
1

J, 43 байта

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

Попробуйте онлайн!

Иногда молчаливый стиль усложняет ситуацию. Но, вероятно, есть способ сделать это молчаливым стилем, который намного более лаконичен, чем этот. Я думаю, что помню лучший способ разбить число на другие цифры, "."0@":но я не могу вспомнить это ...

объяснение

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

Предварительное добавление и удаление 8 должно гарантировать наличие нужного числа нулей (J изменит свои массивы так, чтобы они соответствовали размеру их элемента максимальной длины, а 8 - это 4 цифры в двоичном виде, поэтому он используется).

капуста
источник
1

APL (NARS), 34 символа, 68 байтов

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

небольшой тест:

  h←{(⌈/-⌊/)2⊥¨{⍵⌽a}¨⍳≢a←∊⍉(4⍴2)⊤⍎¨⍕⍵}
  h 9752348061
1002931578825
  h 0
0
RosLuP
источник