カメラを回転させます。宇宙飛行士を救う


23

注:The Martianのマイナーネタバレはこの課題にあります。注意して先読みしてください


火星人は、火星に偶然立ち往生した宇宙飛行士であり植物学者でもある並外れたマーク・ワトニーについてのSF小説です。本のある時点で、マークはNASAと通信しようとしますが、彼らが持っている通信の唯一の手段はカメラです。マークはインデックスカードに書き込むことでメッセージを送信します。NASAはカメラを360度回転させることができるため、NASAはカメラを「はい」または「いいえ」とラベル付けして返信します。

NASAが送信できる唯一のデータはカメラが向いている方向であるため、Markはアルファベット文字のあるカードをポイントしてメッセージを入力できるシステムを考え出します。しかし、文字「az」を使用することは実用的ではありません。この本を引用するには(この回答から、scifi.seに):

30分ごとにyes / noの質問よりも速く話す必要があります。カメラは360度回転でき、アンテナパーツがたくさんあります。アルファベットを作る時間。しかし、文字AからZだけを使用することはできません。26文字と質問カードは、着陸機の周りの27枚のカードになります。それぞれがたった13度の円弧を取得します。JPLがカメラを完璧に向けたとしても、どの文字が意味するのかわからない可能性があります。

したがって、ASCIIを使用する必要があります。それがコンピューターがキャラクターを管理する方法です。各文字には0〜255の数値コードがあります。0〜255の値は2桁の16進数で表現できます。16進数のペアを渡すことで、数字や句読点など、好きな文字を送信できます。

...

そこで、0から9、およびAからFのカードを作成します。これにより、カメラの周りに16枚のカードと質問カードが配置されます。17枚のカードはそれぞれ21度以上を意味します。対処がはるかに簡単です。

NASAのトップソフトウェアエンジニアの1人としての今日の目標は、カメラのさまざまな角度をエンコードするプログラムを作成することです。マークが指し示す17枚のカードは次のとおりです(順番に)。

?0123456789ABCDEF

これらのカードはそれぞれ21度離れているため、カメラをから?0回転するには、カメラを21度回転し、2to 1を-21度回転する必要があります。(それはないです正確に 21、私たちはそれをシンプルに保つために丸めます)soから行くために、このラップをFすることは3105度(5ターン、5 * 21 = 105)です。これは、カメラが遠くまで移動する必要がないため、-252よりも効率的です。

プログラムまたは関数が行う必要があることは次のとおりです。

  1. 入力として文字列を受け取ります。この文字列をsと呼びます。単純にするために、入力は印刷可能なASCIIのみになります。この例では、入力がSTATUS

  2. 各文字を16進表現に変換します。これはに変換さSTATUS53 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]

NASAは効率性に誇りを持っているため、あなたの目標は可能な限り短いコードを書くことです。標準の抜け穴が適用されます。今彼を家に連れて行ってください!


補足:これらのテストケースは手作業で作成されたものであり、多少の痛みを伴うため、若干の不正確さが生じる可能性があります。何かおかしいと感じたら教えてください。:)
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(
ルーク

@Luke Nope。各16進数を分離する必要があるからです。...s.replace(/./g,たとえば"4","8","6","5","6","c"...、while を与えます。...[...s.map(与えるだろう"48","65","6c",...
-ETHproductions

4

C、212 202 199 187バイト

@KritixiLithosのおかげで3バイト節約されました!

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

Python、 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は4バイト長くなります。

別の解決策は、レーザーポインターをカメラに取り付けることです。
すべての印刷可能なアスキー文字と「質問」カードをそれぞれ3.75度で使用できます。

別の代替方法:それぞれ6文字の16カード(22.5度)を使用する:
何らかのT9を実装し、高いニブルを省略することができます。;)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.