Повернуть камеру; спасти астронавта


23

Примечание: второстепенные спойлеры для марсиан в этом вызове. Читайте вперед с осторожностью


«Марсианин» - это научный фантастический роман об экстраординарном астронавте и ботанике Марке Уотни , который случайно оказался на Марсе. В какой-то момент в книге Марк пытается установить связь с НАСА, но единственным средством связи, которое у них есть, является камера. Марк отправляет сообщения, записывая их на учетные карточки, и, поскольку НАСА может поворачивать камеру на 360 градусов, НАСА отправляет ответы обратно, направляя камеру на карточки, помеченные «Да» или «Нет».

Поскольку единственные данные, которые НАСА может отправить, - это направление, в котором находится камера, Марк предлагает систему, в которой они могут указывать на карточки с алфавитными символами для печати сообщений. Но использование букв «az» было бы непрактичным. Процитируем книгу (из этого ответа на scifi.se):

Нам нужно говорить быстрее, чем вопросы да / нет каждые полчаса. Камера может вращаться на 360 градусов, и у меня есть много частей антенны. Время сделать алфавит. Но я не могу просто использовать буквы от A до Z. Двадцать шесть букв плюс моя карточка с вопросом - это двадцать семь карточек вокруг посадочного модуля. Каждый получил бы только 13 градусов дуги. Даже если JPL направит камеру идеально, есть большая вероятность, что я не буду знать, какую букву они имели в виду.

Поэтому мне придется использовать ASCII. Вот так компьютеры управляют персонажами. Каждый символ имеет числовой код от 0 до 255. Значения от 0 до 255 могут быть выражены в виде 2 шестнадцатеричных цифр. Предоставляя мне пары шестнадцатеричных цифр, они могут отправлять любые символы, которые им нравятся, включая цифры, знаки препинания и т. Д.

...

Поэтому я буду делать карточки от 0 до 9 и от А до F. Это позволит разместить 16 карточек вокруг камеры плюс карточку с вопросом. Семнадцать карт означают более 21 градуса каждая. Намного легче иметь дело с.

Ваша цель сегодня, как одного из ведущих разработчиков программного обеспечения в НАСА, - написать программу для кодирования различных ракурсов камеры. Семнадцать карт, на которые Марк должен вам указать: (по порядку):

?0123456789ABCDEF

и каждая из этих карт находится на расстоянии 21 градуса, поэтому, чтобы повернуть камеру от ?к 0, вы должны повернуть камеру на 21 градус, и 2до 1-21 градуса. (Это не совсем 21, но мы округлим, чтобы упростить его). Это оборачивает, так что перейти Fк 3105 градусам (5 витков, 5 * 21 = 105). Это более эффективно, чем -252, так как камера не должна будет двигаться так далеко.

Вот что должна делать ваша программа или функция.

  1. Возьмите строку в качестве ввода. Мы назовем эту строку s . Для простоты скажем, что ввод будет только для печати ASCII. Для нашего примера, скажем, что вход былSTATUS

  2. Преобразуйте каждый символ в его шестнадцатеричное представление. Это будет преобразовано STATUSв 53 54 41 54 55 53.

  3. Распечатайте или верните последовательные повороты, которые потребуется камере, чтобы указать на каждую карточку и вернуться к «карточке вопроса». Для нашего примера это будет:

    6  * 21 = 126   (?-5)
    -2 * 21 = -42   (5-3)
    2  * 21 = 42    (3-5)
    -1 * 21 = -21   (5-4)
    0  * 21 = 0     (4-4)
    -3 * 21 = -63   (4-1)
    4  * 21 = 84    (1-5)
    -1 * 21 = -21   (5-4)
    1  * 21 = 21    (4-4)
    0  * 21 = 0     (5-5)
    0  * 21 = 0     (5-5)
    -2 * 21 = -42   (5-3)
    -4 * 21 = -84   (3-?)
    

    Или в формате массива:

    [126, -42, 42, -21, 0, -63, 84, -21, 21, 0, 0, -42, -84]
    

Обратите внимание, что вы всегда должны брать наименьшее из возможных вращений. Итак, если вход был NO, то есть 4E 4F, вы должны вывести:

5    * 21 = 105
-7   * 21 = -147
7    * 21 = 147
-6   * 21 = -126
1    * 21 = 21

Скорее, чем:

 5   * 21 = 105
 10  * 21 = 210
 -10 * 21 = -210
 11  * 21 = 231
 -16 * 21 = -336

Вот еще несколько проработанных примеров:

Input: CROPS?
ASCII: 43 52 4F 50 53 3F
Worked Example:

5  * 21 = 105
-1 * 21 = -21
2  * 21 = 42
-3 * 21 = -63
2  * 21 = 42
-6 * 21 = -126
7  * 21 = 147
-5 * 21 = -105
5  * 21 = 105
-2 * 21 = -42
0  * 21 = 0
-5  * 21 = -105
1 * 21 = 21

Result: [105 -21 42 -63 42 -126 147 -105 105 -42 0 -105 21]


Input: DDD
ASCII: 44 44 44
Worked Example:

5   * 21 = 105
0   * 21 = 0
0   * 21 = 0
0   * 21 = 0
0   * 21 = 0
0   * 21 = 0
-5  * 21 = -105

Result: [105, 0, 0, 0, 0, 0, -105]


Input: Hello world!
ASCII: 48 65 6c 6c 6f 20 77 6f 72 6c 64 21
Worked example:

5   * 21 = 105
4   * 21 = 84
-2  * 21 = -42
-1  * 21 = -21
1   * 21 = 21
6   * 21 = 126
-6  * 21 = -126
6   * 21 = 126
-6  * 21 = -126
-8  * 21 = -168
4   * 21 = 84
-2  * 21 = -42
7   * 21 = 147
0   * 21 = 0
-1  * 21 = -21
-8  * 21 = -168
-8  * 21 = -168
-5  * 21 = -105
4   * 21 = 84
6   * 21 = 126
-6  * 21 = -126
-2  * 21 = -42
-2  * 21 = -42
-1  * 21 = -21
-2  * 21 = -42

Result: [105 84 -42 -21 21 126 -126 126 -126 -168 84 -42 147 0 -21 -168 -168 -105 84 126 -126 -42 -42 -21 -42]

Поскольку НАСА гордится эффективностью, ваша цель - написать максимально короткий код. Применяются стандартные лазейки. А теперь отвези его домой!


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

Ответы:


5

JavaScript (ES6), 103 99 байт

s=>[...s.replace(/./g,c=>c.charCodeAt().toString(16)),10].map(n=>((24-p-~(p='0x'+n))%17-8)*21,p=-1)

Контрольные примеры


Будет ли это работать? s.replace(/./g,->[...s].map(
Люк

@ Люк Нет, потому что мы должны отделить каждую шестнадцатеричную цифру. ...s.replace(/./g,дает, например "4","8","6","5","6","c"..., пока. ...[...s.map(даст"48","65","6c",...
ETHproductions

4

C 212 202 199 187 байтов

3 байта сохранены благодаря @KritixiLithos!

i;f(a,b){i=abs(a-b);i=8>i?i:17-i;i=a<b&a>b-8?i:a<b&a<b-8?-i:b<a&b>a-8?-i:i;i*=21;}v;g(char*s){for(v=0;*s;s+=v++%2)printf("%d ",v?v%2?f(*s%16,s[1]?s[1]/16:-1):f(*s/16,*s%16):f(-1,*s/16));}

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


1
Я думаю, что вы можете сделать 8>i?i:17-iвместо17-i>i?...
Kritixi Lithos

@KritixiLithos Да, спасибо.
Betseg

3

Питон, 187 178 байт

def g(x):w,z=map('?0123456789abcdef'.index,x);d=w-z;return min(d,d+17*(d<=0 or -1),key=abs)*21
def f(s):s=''.join(map('{:2x}'.format,s.encode()));return[*map(g,zip(s+'?','?'+s))]

Контрольные примеры

for k in ['STATUS', 'NO', 'CROPS?', 'DDD', 'Hello world!']:
    print('Input:  {}\nOutput: {}'.format(k, f(k)))


1

Желе , 21 19 байт

Ob⁴F-;;-I+8%17_8×21

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

Как?

Ob⁴F-;;-I+8%17_8×21 - Main link: string s        e.g. 'e.g.'
O                   - cast to ordinals            [101,     46,       103,      46]
 b                  - convert to base
  ⁴                 -     16                   [[6,   5], [2,  14], [6,   7], [2,  14]]
   F                - flatten                   [6,   5,   2,  14,   6,   7,   2,  14]
    -;              - -1 concatenate      [-1,   6,   5,   2,  14,   6,   7,   2,  14]
      ;-            - concatenate -1      [-1,   6,   5,   2,  14,   6,   7,   2,  14,  -1]
        I           - increments            [  7,  -1,  -3,  12,  -8,   1,  -5,  12, -15]
         +8         - add 8                 [ 15,   7,   5,  20,   0,   9,   3,  20,  -7]
           %17      - mod 17                [ 15,   7,   5,   3,   0,   9,   3,   3,  10]
              _8    - subtract 8            [  7,  -1,  -3,  -5,  -8,   1,  -5,  -5,   2]
                ×21 - multiply by 21        [147, -21, -63,-105,-168,  21,-105,-105,  42]

1

Ом , 20 19 байтов (CP437), не конкурирует

РЕДАКТИРОВАТЬ : сохранить 1 байт, изменив блок карты на повторяющиеся однокомпонентные карты.

Вероятно, было бы немного короче, если бы у меня была неявная векторизация.

`»x»}{»úΓXΓHδ▓_~21*

Объяснение:

`»x»}{»úΓXΓHδ▓_~21*    Main wire, arguments: s

`»x                    Convert char codes of s to hex
   »}                  Split digit pairs
     {                 Flatten
      »ú               Convert digits back to base 10
        ΓXΓH           Append and prepend with -1
            δ          Get deltas between each element of array
             ▓         Map array over...
              _~21*      Negate, multiply by 21

0

PHP, 125 116 байт:

function m($i){static$a;$a+=$d=($i-$a+10)%17-9;echo$d*21,"
";}for(;$c=ord($argv[1][$i++]);m($c%16))m($c/16|0);m(-1);

сломать

function m($i)              // function to turn camera:
{
    static$a;                   // remember angle
    $a+=                        // add delta to angle
    $d=($i-$a+10)%17-9;         // delta: target=nibble value+1-current angle
                                // add 9, modulo 17, -9 -> shortest movement
    echo$d*21,"\n";                 // print delta * 21 and a linebreak
}
for(;$c=ord($argv[1][$i++]);// loop through input characters
    m($c%16))                   // 2. move to low nibble value
    m($c/16|0)                  // 1. move to high nibble value
;
m(-1);                      // move back to "?"

Конечно, 21это довольно неточно и может не сработать для строк длиннее 14 символов; но тогда ... 360/17будет на четыре байта длиннее.

Альтернативным решением было бы прикрепить лазерную указку к камере;
мы могли бы использовать все печатные символы ascii и карточку «вопрос» при 3,75 градусах каждая.

Другой вариант: используйте 16 карт (при 22,5 градусах) по 6 символов в каждой:
реализуйте своего рода T9, и мы можем опустить высокий клев. ;)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.