旋转相机;保存一名宇航员


23

注意:火星人的破坏者正面临这一挑战。仔细阅读


《火星人》是一部科幻小说,讲述的是宇航员和植物学家马克·沃特尼Mark Watney),他偶然被困在火星上。在书中的某一点上,马克尝试与NASA通讯,但他们拥有的唯一通讯方式是摄像头。马克通过在索引卡上书写来发送消息,并且由于NASA可以将摄像机旋转360度,因此NASA通过将摄像机指向标有“是”或“否”的卡来发送回复。

由于NASA只能发送的数据是相机所面对的方向,因此Mark提出了一个系统,可以指向卡片上带有字母字符的卡片来键入消息。但是使用字母“ az”将是不切实际的。引用这本书(从这个答案开始,在scifi.se上):

每半小时,我们需要比肯定/否定的问题说话更快。相机可以旋转360度,并且我有很多天线零件。是时候制作一个字母了。但是我不能只使用字母A到Z。二十六个字母加上我的问题卡将是着陆器周围的二十七张卡片。每个人只会得到13度的弧度。即使JPL完美地对准了相机,我也很可能不知道它们的意思。

因此,我将不得不使用ASCII。这就是计算机管理字符的方式。每个字符都有一个介于0和255之间的数字代码。介于0和255之间的值可以表示为2个十六进制数字。通过给我两对十六进制数字,他们可以发送喜欢的任何字符,包括数字,标点符号等。

...

因此,我将制作0到9,A到F的卡片。这将在相机周围放置16张卡片,再加上问题卡片。十七张牌的意思是每张超过21度。更容易处理。

作为NASA的顶级软件工程师之一,您今天的目标是编写一个程序来对摄像机的各个角度进行编码。马克为您指出的十七张卡片是(按顺序排列):

?0123456789ABCDEF

并且这些卡中的每张相距21度,因此要将相机从旋转?0,您应该将相机旋转21度,21则旋转-21度。(它不完全是 21,但我们将对其进行简化以使其更圆滑)此回绕,因此从F3是105度(5圈,5 * 21 = 105)。这比使用-252更为有效,因为相机不必移动到最远。

这是您的程序或函数必须执行的操作。

  1. 以字符串作为输入。我们将其称为s。为简单起见,我们将说输入将只能是可打印的ASCII。对于我们的示例,假设输入为STATUS

  2. 将每个字符转换为其十六进制表示形式。这将转换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

Answers:


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,因为我们需要将每个十六进制数字分开。...s.replace(/./g,给出例如"4","8","6","5","6","c"...,一会儿。...[...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'3

@KritixiLithos是的,谢谢。
betseg

3

Python,187178字节

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,我们可以忽略高半字节。;)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.