สารวัตรทับทิมอย่างเป็นทางการ


30

นี่คือทับทิมศิลปะ ASCII ง่ายๆ:

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_\/

ในฐานะนักอัญมณีสำหรับ บริษัท อัญมณี ASCII งานของคุณคือการตรวจสอบทับทิมที่เพิ่งซื้อมาใหม่และจดบันทึกเกี่ยวกับข้อบกพร่องที่คุณพบ

โชคดีที่มีข้อบกพร่องเพียง 12 ประเภทเท่านั้นที่เป็นไปได้ และซัพพลายเออร์ของคุณรับประกันว่าไม่มีทับทิมจะมีข้อบกพร่องมากกว่าหนึ่งข้อ

12 ข้อบกพร่องที่สอดคล้องกับการเปลี่ยนของหนึ่งในชั้น 12 _, /หรือ\ตัวละครของทับทิมที่มีอักขระช่องว่าง ( ) ปริมณฑลด้านนอกของทับทิมไม่เคยมีข้อบกพร่อง

ข้อบกพร่องจะถูกกำหนดหมายเลขตามตัวอักษรด้านในซึ่งมีช่องว่างอยู่

defect numbers

ดังนั้นทับทิมที่มีข้อบกพร่อง 1 จะมีลักษณะดังนี้:

  ___
 /\_/\
/_/  _\
\ \_/ /
 \/_\/

ทับทิมที่มีตำหนิ 11 มีลักษณะดังนี้:

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \ _\/

มันเป็นความคิดเดียวกันสำหรับข้อบกพร่องอื่น ๆ ทั้งหมด

ท้าทาย

เขียนโปรแกรมหรือฟังก์ชั่นที่รับสายทับทิมเดียวที่อาจชำรุด ควรพิมพ์หรือส่งคืนหมายเลขข้อบกพร่อง หมายเลขข้อบกพร่องคือ 0 ถ้าไม่มีข้อบกพร่อง

รับอินพุตจากไฟล์ข้อความ stdin หรืออาร์กิวเมนต์ฟังก์ชันสตริง ส่งคืนหมายเลขข้อบกพร่องหรือพิมพ์เป็น stdout

คุณอาจสันนิษฐานได้ว่าทับทิมมีการขึ้นบรรทัดใหม่ คุณไม่สามารถสันนิษฐานได้ว่ามันมีช่องว่างต่อท้ายหรือขึ้นบรรทัดใหม่

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ ( ตัวนับไบต์ที่มีประโยชน์ )

กรณีทดสอบ

ทับทิมชนิดที่แน่นอน 13 ชนิดตามด้วยผลลัพธ์ที่คาดหวัง:

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_\/
0
  ___
 /\_/\
/_/  _\
\ \_/ /
 \/_\/
1
  ___
 /\ /\
/_/ \_\
\ \_/ /
 \/_\/
2
  ___
 /\_/\
/_  \_\
\ \_/ /
 \/_\/
3
  ___
 /\_/\
/_/ \_\
\  _/ /
 \/_\/
4
  ___
 /\_/\
/_/ \_\
\ \ / /
 \/_\/
5
  ___
 /\_/\
/_/ \_\
\ \_  /
 \/_\/
6
  ___
 /\_/\
/_/ \ \
\ \_/ /
 \/_\/
7
  ___
 /\_ \
/_/ \_\
\ \_/ /
 \/_\/
8
  ___
 / _/\
/_/ \_\
\ \_/ /
 \/_\/
9
  ___
 /\_/\
/ / \_\
\ \_/ /
 \/_\/
10
  ___
 /\_/\
/_/ \_\
\ \_/ /
 \ _\/
11
  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_ /
12

หากต้องการชี้แจงทับทิมไม่สามารถมีช่องว่างต่อท้ายได้ใช่ไหม
เครื่องมือเพิ่มประสิทธิภาพ


@ Calvin'sHobbies อาจถือว่าเรายังนำเข้าไม่ได้มีการขึ้นบรรทัดใหม่?
orlp

@ หรือไม่ใช่ นั่นเป็นจุดรวมของเดือนพฤษภาคม
งานอดิเรกของ Calvin

ทับทิมมีความสมมาตร ดังนั้นข้อผิดพลาด # 7 ไม่ควรเหมือนกับข้อผิดพลาด # 10 ใช่ไหม
DavidC

คำตอบ:


13

CJam, 27 23 ไบต์

F7EC5ZV4DI8G6]qBb67%J%#

แปลงฐาน 11, ใช้ mod 67, ใช้ mod 19 ของผลลัพธ์แล้วค้นหาดัชนีของสิ่งที่คุณมีในอาร์เรย์

[15, 7, 14, 12, 5, 3, 0, 4, 13, 18, 8, 16, 6]

มายากล!

ลองมันออนไลน์


34

Ruby 2.0, 69 ไบต์

#!ruby -Kn0rdigest
p'×ñF<ìX‚ɲŸ_'.index Digest::MD5.digest(gets)[0]

Hexdump (เพื่อแสดงข้อมูลไบนารีในสตริงอย่างซื่อสัตย์):

00000000  23 21 72 75 62 79 20 2d  4b 6e 30 72 64 69 67 65  |#!ruby -Kn0rdige|
00000010  73 74 0a 70 27 d7 f1 46  3c 1f ec 58 82 c9 b2 9f  |st.p'..F<..X....|
00000020  5f 02 27 2e 69 6e 64 65  78 20 44 69 67 65 73 74  |_.'.index Digest|
00000030  3a 3a 4d 44 35 2e 64 69  67 65 73 74 28 67 65 74  |::MD5.digest(get|
00000040  73 29 5b 30 5d                                    |s)[0]|

คำอธิบาย:

  1. -Knตัวเลือกอ่านแฟ้มแหล่งที่มาเป็นASCII-8BIT(binary)
  2. -0ตัวเลือกที่ช่วยให้getsการอ่านทั้งในการป้อนข้อมูล (และไม่ได้เป็นเพียงหนึ่งบรรทัด)
  3. -rdigestโหลดตัวเลือกโมดูลที่ให้บริการdigestDigest::MD5
  4. จากนั้นรหัสจะทำ MD5 ของอินพุตรับไบต์แรกของการแยกย่อยและรับดัชนีในสตริงไบนารีที่กำหนด

Lucky that MD5 is unique on first char itself
Optimizer

15
No luck is required. Each byte has 256 possibilities, so the first byte being different for 13 hashes isn't that unusual. But if they collided for any reason, I'd just use the second byte of the hash.
Chris Jester-Young

14
Write a Ruby inspector in Ruby. Naturally!
Mast

Next challenge: Inspect this post itself
Redwolf Programs

7

Julia, 90 59 bytes

Definitely not the shortest, but the fair maiden Julia takes great care in the inspection of the royal rubies.

s->search(s[vec([18 10 16 24 25 26 19 11 9 15 32 34])],' ')

This creates a lambda function which accepts a string s and returns the corresponding ruby defect number. To call it, give it a name, e.g. f=s->....

Ungolfed + explanation:

function f(s)
    # Strings can be indexed like arrays, so we can define d to
    # be a vector of indices corresponding to potential defect
    # locations

    d = vec([18 10 16 24 25 26 19 11 9 15 32 34])

    # Check the specified locations for defects, returning the
    # defect number as the index where a space was found and
    # was not expected. If no spaces are found, 0 is returned.

    search(s[d], ' ')
end

Examples:

julia> f("  ___
 /\\ /\\
/_/ \\_\\
\\ \\_/ \/
 \\/_\\/")
2

julia> f("  ___
 /\\_/\\
/_/ \\_\\
\\ \\_/ \/
 \\/_\\/")
0

Note that backslashes have to be escaped in the input. I confirmed with @Calvin'sHobbies that it's okay.

Let me know if you have any questions or suggestions!


Edit: Saved 31 bytes with help from Andrew Piliser!


You can get rid of the for loop with search and array indexing. s->(d=reshape([18 10 16 24 25 26 19 11 9 15 32 34],12);search(s[d],' ')). I don't like the reshape, but I couldn't think of a shorter way to get a 1d array.
Andrew says Reinstate Monica

@AndrewPiliser: Thanks, I really appreciate your input! I edited to use your suggestion. Also, a shorter way than reshape() is to use vec(). :)
Alex A.

7

><> (Fish), 177 bytes

This is a long but unique solution. The program contains no arithmetic or branching apart from inserting input characters into fixed places in the code.

Notice that all the inspected ruby-building characters (/ \ _) can be "mirrors" in the ><> code that change the direction of the instruction pointer (IP).

We can use these input characters to build a maze from them with the code-modifying instruction p and at every exit (which created by a missing mirror in the input) we can print the corresponding number.

iiiiiiiii19pi1cpi18piiii2bpi27pii28pi3apiiiii37pi49pi36piiiii00pi45pii46p

    ;
   ;n
  ;nb
 ;n6S    0n;
 n3SB   cn;
 8SB!  4n;
 SB!  1n;
>B! U9n;
 ! U5
  U7n
 Uan;
 2n;
 n;
 ;

The S B U letters are the ones changed to / \ _ respectively. If the input is a full ruby the final code becomes:

\iiiiiiii19pi1cpi18piiii2bpi27pii28pi3apiiiii37pi49pi36piiiii00pi45pii46p

    ;
   ;n
  ;nb
 ;n6/    0n;
 n3/\   cn;
 8/\!  4n;
 /\!  1n;
>\! _9n;
 ! _5
  _7n
 _an;
 2n;
 n;
 ;

You can try out the program with this great online visual interpreter. As you can't input newlines there you have to use some dummy characters instead so you can input a full ruby as e.g. SS___LS/\_/\L/_/S\_\L\S\_/S/LS\/_\/. (Spaces also changed to S's because of markdown.)


5

CJam, 41 31 29 28 bytes

"-RI)11a!"q103b1e3%A/c#

As usual, for non printable characters, follow this link.

Try it online here

Explanation soon


Previous approach:

Pretty sure this can be reduced by changing the digits/conversion logic. But here goes the first attempt:

"<KJ[]\"O=":iqN-"/\\_ "4,er4b1e3%A/#

As usual, use this link for unprintable characters.

The logic is pretty simple

  • "Hash for each defect":i - This gets me the hash per defect as the index
  • qN-"/\\_ "4,er - this converts the characters to numbers
  • 4b1e3%A/ - this is the unique number in the base converted number
  • # Then I simply find the index of the unique number in the hash

Try it online here


So close, I'm 1 character shorter than you!
orlp

Oh, I already have 28. Was too busy to update
Optimizer

I think my answer is optimal for Pyth. Pyth really needs a hash function (.h right now is useless because it uses the built-in unreliable and bad hash()), until then I can't do better.
orlp

4

Slip, 123 108 + 3 = 111 bytes

^6 (`\\`_.?<?.?[ _]?|`_(`\.?(<.?|>)|`/.?.?>.?.?).?)| `_(`\.?<.?>?.?.?|`/(.?>.?.?.?|<`_))| `/\`_.?(.<.?>?.?)?

Run with the n and o flags, i.e.

py -3 slip.py regex.txt input.txt no

Alternatively, try it online.


Slip is a regex-like language which was made as part of the 2D pattern matching challenge. Slip can detect the location of a defect with the p position flag via the following program:

^6? `_[/\]|( `/|^6 `\)\`_

which looks for one of the following patterns (here S denotes here the match starts):

S_/    S_\    /_S    \_S    S/      _
                              _      \S

Try it online — coordinates are outputted as an (x, y) pair. Everything reads like a normal regex, except that:

  • ` is used for escaping,
  • <> turn the match pointer left/right respectively,
  • ^6 sets the match pointer to face leftward, and
  • \ slips the match pointer orthogonally to the right (e.g. if the pointer's facing rightward then it goes down a row)

But unfortunately, what we need is a single number from 0 to 12 saying which defect was detected, not where it was detected. Slip only has one method of outputting a single number — the n flag which outputs the number of matches found.

So to do this we expand the above regex to match the correct number of times for each defect, with the help of the o overlapping match mode. Broken down, the components are:

1 11:    `_`\.?<.?>?.?.?
2 10:    `/\`_.?(.<.?>?.?)?
4 9:     `_`/(.?>.?.?.?|<`_)
3 12:   ^6 `_`/.?.?>.?.?.?
5 7:    ^6 `\\`_.?<?.?[ _]?
6 8:    ^6 `_`\.?(<.?|>).?

Yes, that's an exccessive use of ? to get the numbers right :P


Haha, amazing. I need to add more types of output to my language.
BMac

4

JavaScript (ES6), 67 72

Simply looks for blanks in the given 12 locations

Edit Saved 5 bytes, thx @apsillers

F=b=>[..."0h9fnopia8evx"].map((v,i)=>b[parseInt(v,34)]>' '?0:d=i)|d

Test In Firefox / FireBug console

x='  ___\n /\\_/\\\n/_/ \\_\\\n\\ \\_/ /\n \\/_\\/' // no defects
;[...x].forEach((c,p,a)=>{
  a[p]=' ' // put a blank
  y=a.join('') // rebuild a string
  d=F(y) // check
  if (d) console.log('\n'+y+'\n'+d) // if defect, output
  a[p]=c // remove the blamk
})

Output

  ___
 / _/\
/_/ \_\
\ \_/ /
 \/_\/
9

  ___
 /\ /\
/_/ \_\
\ \_/ /
 \/_\/
2

  ___
 /\_ \
/_/ \_\
\ \_/ /
 \/_\/
8

  ___
 /\_/\
/ / \_\
\ \_/ /
 \/_\/
10

  ___
 /\_/\
/_  \_\
\ \_/ /
 \/_\/
3

  ___
 /\_/\
/_/  _\
\ \_/ /
 \/_\/
1

  ___
 /\_/\
/_/ \ \
\ \_/ /
 \/_\/
7

  ___
 /\_/\
/_/ \_\
\  _/ /
 \/_\/
4

  ___
 /\_/\
/_/ \_\
\ \ / /
 \/_\/
5

  ___
 /\_/\
/_/ \_\
\ \_  /
 \/_\/
6

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \ _\/
11

  ___
 /\_/\
/_/ \_\
\ \_/ /
 \/_ /
12

@apsillers it's good and even better, thanks. As the input string always start with ' ',the leading 0 force the initialization of d to i at first loop, so the 'd=0' can be remove.
edc65

2

C, 98 84 bytes

g(char*b){char*c="/'-5670(&,=?",*a=c;for(;*c&&!(*b=b[*c++-30]-32?0:c-a););return*b;}

UPDATE: A tad bit more clever about the string, and fixed an issue with non-defected rubies.

Unraveled:

g(char*b){
    char*c="/'-5670(&,=?",*a=c;
    for(;*c&&!(*b=b[*c++-30]-32?0:c-a);)
        ;
    return*b;
}

Quite straightforward, and just under 100 bytes.

For testing:

#include "stdio.h"
int main() {
    char b[100];
    scanf("%35c", b);
    printf("%d\n", g(b));
    return 0;
}

Input to STDIN.

How it works

Each defect in the ruby is located at a different character. This list shows where each defect occurs in the input string:

Defect 1: 17
Defect 2: 9
Defect 3: 15
Defect 4: 23
Defect 5: 24
Defect 6: 25
Defect 7: 18
Defect 8: 10
Defect 9: 8
Defect 10: 14
Defect 11: 31
Defect 12: 33

Since making an array of {17,9,15,23,24,25,18,10,8,14,31,33} costs a lot of bytes, we find a shorter way to create this list. Observe that adding 30 to each number results in a list of integers that could be represented as printable ASCII characters. This list is as follows: "/'-5670(&,=?". Thus, we can set a character array (in the code, c) to this string, and simply subtract 30 from every value we retrieve from this list to get our original array of integers. We define a to be equal to c for keeping track of how far along the list we have gotten. The only thing left in the code is the for loop. It checks to make sure we have not hit the end of c yet, and then checks if the character of b at the current c is a space(ASCII 32). If it is, we set the first, unused element of b to the defect number and return it.


2

Python 2, 146 88 86 71 bytes

The function f tests each segment location and returns the index of the defect segment. A test on the first byte in the input string ensures that we return 0 if no defects are found.

We now pack the segment offsets into a compact string and use ord() to recover them:

f=lambda s:sum(n*(s[ord('ARJPXYZSKIO`b'[n])-65]<'!')for n in range(13))

Testing with a perfect ruby:

f('  ___\n /\\_/\\\n/_/ \\_\\\n\\ \\_/ /\n \\/_\\/')
0

Testing with segment 2 replaced by a space:

f('  ___\n /\\ /\\\n/_/ \\_\\\n\\ \\_/ /\n \\/_\\/')
2

EDIT: Thanks to @xnor for the nice sum(n*bool for n in...) technique.

EDIT2: Thanks to @Sp3000 for extra golfing tips.


2
I think you can save chars by using an indicator-sum sum(n*(s[...]==' ')for ...).
xnor

1
Considering that the replaced chars are all after space, you can probably do something like <'!' instead of ==' ' for a byte. You can also generate the list with map(ord, ...), but I'm not sure how you feel about unprintables :)
Sp3000

1

Pyth, 35 31 28 bytes

hx"*6#,54@"C%imCds.zT67

Requires a patched Pyth, the current latest version of Pyth has a bug in .z that strips off trailing characters.

This version doesn't use a hash function, it abuses the base conversion function in Pyth to compute a very stupid, but working hash. Then we convert that hash to a character and look its index up in a string.

The answer contains unprintable characters, use this Python3 code to generate the program accurately on your machine:

garbage = [42, 22, 54, 35, 44, 28, 31, 53, 52, 64, 16, 11]
prg = 'hx"' + "".join(chr(c) for c in garbage) +'"C%imCds.zT67'
open("golf_gen.pyth", "w").write(prg)
print(len(prg))

1

Haskell, 73 bytes

f l=last[x|x<-[0..12],l!!([0,17,9,15,23,24,25,18,10,8,14,31,33]!!x)==' ']

Same strategy as many other solutions: looking for spaces at the given locations. The lookup returns a list of indices from which I take the last element, because there is always a hit for index 0.


0

05AB1E, 16 bytes

•W)Ì3ô;4(•₆вèðk>

Try it online or verify all test cases.

Explanation:

W3ô;4(•        # Push compressed integer 2272064612422082397
          ₆в      # Converted to Base-36 as list: [17,9,15,23,24,25,18,10,8,14,31,33]
            è     # Index each into the (implicit) input-string
             ðk   # Get the 0-based index of the first space in the indexed characters
                  # (-1 if not found, which means the ruby had no defects)
               >  # And increase it by 1 (which is output implicitly as result)

See this 05AB1E tip of mine (sections How to compress large integers? and How to compress integer lists?) to understand why •W)Ì3ô;4(• is 2272064612422082397 and •W)Ì3ô;4(•₆в is [17,9,15,23,24,25,18,10,8,14,31,33].

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.