Xoay camera; cứu một phi hành gia


23

Lưu ý: Những kẻ phá hỏng nhỏ cho The Martian nằm trong thử thách này. Đọc trước một cách thận trọng


The Martian là một tiểu thuyết khoa học viễn tưởng về phi hành gia và nhà thực vật học ngoại hạng, Mark Watney , người đã vô tình bị mắc kẹt trên sao Hỏa. Tại một thời điểm trong cuốn sách, Mark cố gắng liên lạc với NASA, nhưng phương tiện liên lạc duy nhất họ có là một chiếc máy ảnh. Mark gửi tin nhắn bằng cách viết trên thẻ chỉ mục và vì NASA có thể xoay camera 360 độ, NASA gửi trả lời lại bằng cách chỉ camera vào các thẻ có nhãn "Có" hoặc "Không".

Vì dữ liệu duy nhất mà NASA có thể gửi là hướng máy ảnh hướng tới, Mark đưa ra một hệ thống nơi họ có thể chỉ vào các thẻ có ký tự bảng chữ cái trên đó để nhập tin nhắn. Nhưng sử dụng các chữ cái 'az' sẽ không thực tế. Để trích dẫn cuốn sách (từ câu trả lời này , trên scifi.se):

Chúng ta sẽ cần nói nhanh hơn có / không có câu hỏi mỗi nửa giờ. Máy ảnh có thể xoay 360 độ, và tôi có nhiều bộ phận ăng ten. Thời gian để làm một bảng chữ cái. Nhưng tôi không thể chỉ sử dụng các chữ cái từ A đến Z. Hai mươi sáu chữ cái cộng với thẻ câu hỏi của tôi sẽ là hai mươi bảy thẻ xung quanh tàu đổ bộ. Mỗi người chỉ được 13 độ cung. Ngay cả khi JPL chỉ máy ảnh một cách hoàn hảo, vẫn có cơ hội tốt để tôi không biết họ muốn nói đến bức thư nào.

Vì vậy, tôi sẽ phải sử dụng ASCII. Đó là cách máy tính quản lý nhân vật. Mỗi ký tự có một mã số từ 0 đến 255. Giá trị từ 0 đến 255 có thể được biểu thị dưới dạng 2 chữ số thập lục phân. Bằng cách cho tôi các cặp chữ số hex, họ có thể gửi bất kỳ ký tự nào họ thích, bao gồm số, dấu chấm câu, v.v.

...

Vì vậy, tôi sẽ tạo các thẻ từ 0 đến 9 và từ A đến F. Điều đó tạo ra 16 thẻ để đặt xung quanh máy ảnh, cộng với thẻ câu hỏi. Mười bảy thẻ có nghĩa là hơn 21 độ mỗi. Dễ dàng hơn nhiều để đối phó với.

Mục tiêu của bạn ngày hôm nay, với tư cách là một trong những kỹ sư phần mềm hàng đầu tại NASA, là viết một chương trình để mã hóa các góc khác nhau của máy ảnh. Mười bảy thẻ mà Mark có để bạn chỉ vào là (theo thứ tự):

?0123456789ABCDEF

và mỗi thẻ này cách nhau 21 độ, vì vậy để xoay camera từ ?sang 0, bạn nên xoay camera 21 độ và 2đến 1-21 độ. (Không chính xác là 21, nhưng chúng ta sẽ làm tròn để đơn giản hơn) Kết thúc tốt đẹp này, do đó, đi từ Fđến 3là 105 độ (5 lượt, 5 * 21 = 105). Điều này hiệu quả hơn so với đi -252, vì máy ảnh sẽ không phải di chuyển xa.

Đây là những gì chương trình hoặc chức năng của bạn phải làm.

  1. Lấy một chuỗi làm đầu vào. Chúng tôi sẽ gọi chuỗi này s . Để đơn giản, chúng tôi sẽ nói rằng đầu vào sẽ chỉ có thể in được ASCII. Ví dụ của chúng tôi, giả sử rằng đầu vào làSTATUS

  2. Chuyển đổi mỗi ký tự thành biểu diễn thập lục phân của nó. Điều này sẽ chuyển đổi STATUSsang 53 54 41 54 55 53.

  3. In ra hoặc trả lại các mức độ liên tiếp mà máy ảnh sẽ cần thực hiện để chỉ vào từng thẻ và quay lại "Thẻ câu hỏi". Ví dụ của chúng tôi, đây sẽ là:

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

    Hoặc, ở định dạng mảng:

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

Lưu ý rằng bạn phải luôn luôn thực hiện các phép quay nhỏ nhất có thể. Vì vậy, nếu đầu vào NO4E 4F, bạn nên xuất ra:

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

Thay vì:

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

Dưới đây là một số ví dụ hoạt động tốt hơn:

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]

Vì NASA tự hào về hiệu quả, mục tiêu của bạn là viết mã ngắn nhất có thể. Tiêu chuẩn áp dụng. Bây giờ hãy mang anh ấy về nhà!


Lưu ý bên lề: Những trường hợp thử nghiệm này được thực hiện bằng tay và là một nỗi đau, vì vậy có thể có một số điểm không chính xác nhỏ. Xin vui lòng cho tôi biết nếu bất cứ điều gì có vẻ sai. :)
DJMcMayhem

Câu trả lời:


5

JavaScript (ES6), 103 99 byte

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

Các trường hợp thử nghiệm


Điều này sẽ làm việc? s.replace(/./g,->[...s].map(
Luke

@Luke Không, bởi vì chúng ta cần tách ra từng chữ số thập lục phân. ...s.replace(/./g,đưa ra ví dụ "4","8","6","5","6","c"..., trong khi. ...[...s.map(sẽ cung cấp"48","65","6c",...
ETHproductions

4

C, 212 202 199 187 byte

3 byte được lưu nhờ @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));}

Hãy thử trực tuyến!


1
Tôi nghĩ bạn có thể làm 8>i?i:17-ithay vì17-i>i?...
Kritixi Lithos

@KritixiLithos yup, cảm ơn.
betseg

3

Python, 187 178 byte

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

Các trường hợp thử nghiệm

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


1

Thạch , 21 19 byte

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

Hãy thử trực tuyến!

Làm sao?

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

Ohm , 20 19 byte (CP437), không cạnh tranh

EDIT : Đã lưu 1 byte bằng cách thay đổi khối bản đồ thành các bản đồ đơn thành phần lặp lại.

Có lẽ sẽ ngắn hơn một chút nếu tôi có vector hóa ngầm.

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

Giải trình:

`»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 byte:

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

phá vỡ

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 "?"

Tất nhiên, 21khá không chính xác và có thể thất bại đối với các chuỗi dài hơn 14 ký tự; nhưng sau đó ... 360/17sẽ dài hơn bốn byte.

Một giải pháp thay thế sẽ là gắn một con trỏ laser vào máy ảnh;
chúng ta có thể sử dụng tất cả các ký tự ascii có thể in và thẻ "câu hỏi" ở mức 3,75 độ mỗi cái.

Một cách khác: Sử dụng 16 thẻ (ở 22,5 độ) với 6 ký tự mỗi thẻ:
thực hiện một số loại T9 và chúng ta có thể bỏ qua mức độ cao. ;)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.