ช่วยในการจำ 23940


19

ระบบที่สำคัญคือช่วยในการจำอุปกรณ์สำหรับการแปลงตัวเลขเป็นคำพูดเพื่อให้พวกเขาสามารถจดจำได้ง่ายขึ้น

มันขึ้นอยู่กับวิธีที่คำพูดออกเสียง แต่เพื่อให้สิ่งต่าง ๆ ง่ายขึ้นสำหรับความท้าทายเราจะกังวลเฉพาะกับวิธีการสะกดคำ ซึ่งหมายความว่าจะมีการแปลงที่ไม่ถูกต้อง แต่ก็ไม่เป็นไร

ในการแปลงตัวเลขเป็นคำโดยใช้ระบบหลักที่ง่ายของเรา:

  • แทนที่แต่ละ0ด้วยหรือs z(บางคนอาจเป็นsและบางคนอาจเป็นzเหมือนกันไปด้านล่าง)
  • แทนที่แต่ละ1กับtหรือหรือdth
  • แทนที่แต่ละกับ2n
  • แทนที่แต่ละกับ3m
  • แทนที่แต่ละกับ4r
  • แทนที่แต่ละกับ5l
  • แทนที่แต่ละ6กับjหรือหรือshch
  • แทนที่แต่ละ7กับkหรือcหรือหรือgq
  • แทนที่แต่ละ8ด้วยหรือfv
  • แทนที่แต่ละ9ด้วยหรือpb
  • เพิ่มตัวอักษรaehiouwxyใดก็ได้ในปริมาณใด ๆ ที่จะทำให้คำภาษาอังกฤษที่จริงถ้าเป็นไปได้
    ยกเว้นอย่างเดียวคือว่าhอาจจะไม่ถูกแทรกหลังหรือsc

ตัวเลขอาจเป็นสตริงใด ๆ ของตัวเลข 0-9 (ไม่มีทศนิยมหรือเครื่องหมายจุลภาคหรือเครื่องหมาย)
คำสามารถประกอบด้วยตัวอักษรตัวพิมพ์เล็ก az เท่านั้น

ตัวอย่าง

จำนวน32ต้องถูกแปลงเป็น?m?n?, ซึ่ง?แทนสตริงใด ๆ ที่ จำกัด ที่ทำจากตัวอักษรaehiouwxy(สตริงจากmonoid อิสระถ้าคุณต้องการ) : มีหลายวิธีนี้อาจจะทำให้เป็นคำภาษาอังกฤษที่แท้จริงmane, moon, yeomanฯลฯ

จำนวน05จะถูกแปลงเป็นหรือ?s?l? ?z?l?เป็นไปได้ที่บางคนมีeasily, และhassle ไม่อนุญาตให้ใช้hazelคำshawlนี้เพราะhอาจไม่ได้อยู่หลังs; 65มันจะอ่านไม่ถูกต้องเป็น

ท้าทาย

เขียนโปรแกรมหรือฟังก์ชั่นที่ใช้สายอักขระของตัวเลข 0-9 และค้นหาคำทั้งหมดที่สามารถแปลงเป็นโดยใช้ระบบช่วยจำที่สำคัญแบบย่อ

โปรแกรมของคุณสามารถเข้าถึงไฟล์ข้อความรายการคำศัพท์ที่กำหนดว่าคำภาษาอังกฤษที่ "แท้จริง" ทั้งหมดคืออะไร มีคำ az ตัวพิมพ์เล็กหนึ่งตัวในแต่ละบรรทัดของไฟล์นี้และคุณอาจเลือกที่จะคิดว่ามันมีบรรทัดใหม่ต่อท้าย นี่คือรายการของคำศัพท์จริงที่คุณสามารถใช้สำหรับการทดสอบ คุณสามารถสมมติว่าไฟล์รายการคำนี้เรียกว่าf(หรือบางอย่างที่ยาวกว่า) และอยู่ในไดเรกทอรีที่สะดวก

สำหรับการลงโทษ 35 ไบต์ (เพิ่ม 35 คะแนนของคุณ) คุณอาจถือว่ารายการคำศัพท์ถูกโหลดลงในตัวแปรเป็นรายการสตริงแล้ว นี่คือส่วนใหญ่สำหรับภาษาที่ไม่สามารถอ่านไฟล์ แต่การส่งใด ๆ อาจใช้ประโยชน์จากมัน

โปรแกรมของคุณจะต้องส่งออกคำทั้งหมดในรายการคำที่สามารถป้อนจำนวนการแปลงเป็น พวกเขาควรจะพิมพ์ไปยัง stdout (หรือคล้ายกัน) หนึ่งคนต่อบรรทัด (กับบรรทัดใหม่ต่อท้ายไม่จำเป็น) หรือพวกเขาสามารถกลับมาเป็นรายการของสตริงถ้าคุณเลือกที่จะเขียนฟังก์ชั่น รายการคำไม่จำเป็นต้องเรียงตามตัวอักษรและผลลัพธ์ไม่จำเป็นต้องเป็นอย่างใดอย่างหนึ่ง

หากไม่มีคำที่เป็นไปได้ผลลัพธ์ (หรือรายการ) จะว่างเปล่า เอาต์พุตยังเป็นค่าว่างหากสตริงว่างเป็นอินพุต

รับอินพุตผ่าน stdin, บรรทัดคำสั่งหรือเป็นอาร์กิวเมนต์สตริงไปยังฟังก์ชัน รายการคำหรือชื่อไฟล์ไม่ควรเป็นส่วนหนึ่งของอินพุตเพียงสตริงหลัก

คุณกำลังจับคู่คำเดียวเท่านั้นในรายการคำไม่ใช่ลำดับของคำ คำnoonอาจเป็นหนึ่งในผลลัพธ์สำหรับ22แต่ลำดับของคำno oneจะไม่

กรณีทดสอบ

สมมติว่านี่เป็นรายการคำ:

stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
zdnmrlshchvb
sthnmrlchgvb
shthnmrlchgvb
bob
pop
bop
bopy
boppy

ข้อมูลที่ป้อน0123456789ควรให้ทุกคำยกเว้นzdnmrlshchvbและshthnmrlchgvb:

stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb

อินพุต99ควรให้:

bob
pop
bop
bopy

(คำที่ส่งออกอาจอยู่ในลำดับใด ๆ )

เกณฑ์การให้คะแนน

การส่งที่สั้นที่สุดในหน่วยไบต์ชนะ Tiebreaker จะไปยังการส่งที่โพสต์ก่อน

เว็บไซต์ที่เกี่ยวข้อง Nifty: numzi.com


1
คุณได้รับแนวคิดสำหรับการท้าทายนี้จากวิดีโอนี้ไหม เพราะที่จริงฉันเพิ่งดูเมื่อวานนี้ : P
Doorknob

1
@Doorknob ไม่ใช่วิดีโอ แต่เป็นผู้ชายคนนั้น ปีที่ผ่านมาผมได้รับอย่างใดอย่างหนึ่งของการบรรยายหลักสูตรที่ดี เขาเป็นคนใจดี แต่ก็ทำสิ่งที่เรียบร้อยจริงๆ :)
งานอดิเรกของ Calvin

1
หมายเหตุสำหรับผู้ที่สนใจในการใช้ระบบสำคัญช่วยในการจำในชีวิตจริง: มันเป็นเพียงเสียงที่มีความสำคัญไม่ใช่การสะกดคำ ดังนั้น "c" ในขณะที่ระบุไว้ที่นี่เป็นความหมาย 7 อาจหมายถึง 0 จริง ๆ ถ้าในคำนั้นออกเสียงด้วยเสียง "s" (ดังใน "ace" = 0) อย่างไรก็ตามฉันแน่ใจว่า OP ทำให้การท้าทายเป็นเรื่องง่ายขึ้นเนื่องจากพจนานุกรมที่มีการออกเสียงเต็มรูปแบบนั้นทำได้ยากกว่ารายการคำศัพท์ธรรมดา โอ้และหนึ่งการแสดงผลของ 23940 คือ "ตัวเลข"
ErikE

@ErikE ฉันรัฐที่เรากำลังใช้รุ่นตามการสะกดคำในประโยคที่สองของการโพสต์ ...
คาลวินอดิเรก

ฉันเห็นว่าตอนนี้แม้ว่าฉันจะคิดถึงมันในตอนแรก - แต่มันก็ยังดูเหมือนว่าคำอธิบายของคุณอาจจะถูกเนื้อออกเล็กน้อยและตัวอย่างหรือสองให้
ErikE

คำตอบ:


6

Perl, 87 84

open A,f;"@ARGV"eq s/[cs]h/j/gr=~y/stnmrljkfpzdcgqvb\0-z/0-90177789/dr&&print for<A>

รับอินพุตเป็นพารามิเตอร์บรรทัดคำสั่ง:

$perl m.pl 23940

สามารถทำค่อนข้างสั้นถ้ารายการคำจะได้รับอนุญาตในอินพุตมาตรฐาน:

$perl -lnE'INIT{$;=pop}$;eq s/[cs]h/j/gr=~y/stnmrljkfpzdcgqvba-z/0-90177789/dr&&say' 99 <f

สิ่งที่ไม่Aอยู่ในค่าเฉลี่ยopen A,f?
feersum

@feersum ตัวจัดการไฟล์ใช้เพื่ออ่านไฟล์ในภายหลัง ( <A>)
nutki

4

Python 2, 215 208 ไบต์

โซลูชัน Python นี้สร้าง regex จากส่วนที่ทำดัชนีโดยอาร์กิวเมนต์บรรทัดคำสั่งจากนั้นทดสอบแต่ละคำด้วย regex นั้น (ค่อนข้างใหญ่)

import re,sys
a='[sz] (d|th?) n m r l (j|sh|ch) [kcgq] [fv] [pb]'.split()
b=z='((?<![sc])h|[aeiouwxy])*'
for i in sys.argv[1]:b+=a[int(i)]+z
for d in open('f'):
 d=d.strip()
 if re.match('^'+b+'$',d):print d

แหล่งต้นฉบับก่อนตัวลดขนาด:

import re,sys
regexbits = '[sz] (d|th?) n m r l (j|sh|ch) [kcgq] [fv] [pb]'.split()

regex = other = '((?<![sc])h|[aeiouwxy])*'
for i in sys.argv[1] :
    regex += regexbits[int(i)] + other
print regex     # DEBUG

for word in open('f'):
    word = word.strip()
    if re.match('^'+regex+'$', word) :
        print word

ตัวอย่างเช่น regex สำหรับการทดสอบ99คือ:

^((?<![sc])h|[aeiouwxy])*[pb]((?<![sc])h|[aeiouwxy])*[pb]((?<![sc])h|[aeiouwxy])*$

(?<![sc])hบิตคือ "ดูเบื้องหลังการยืนยันเชิงลบ" องค์ประกอบที่ทำให้แน่ใจว่าhไม่ปฏิบัติตามsหรือcในส่วนฟิลเลอร์ทั่วไป

ขอบคุณคาลวิน ความท้าทายนี้ทำให้ฉันได้แปรงทักษะ regex ที่เป็นสนิมของฉัน


b=c='((?<![sc])h|[aeiouwxy])*'จะบันทึกสองไบต์
matsjoyce

t|th -> th?บันทึกไบต์
Sp3000

คุณสามารถหลีกเลี่ยงแผนที่โดยใช้ int (i) โดยตรง
xnor

ขอบคุณ matsjoyce, Sp3000 และ xnor สำหรับเคล็ดลับการตีกอล์ฟที่มีประโยชน์ แก้ไขแล้วพร้อมกับคำแนะนำที่นำไปใช้
Logic Knight

2

Python 3, 170

import sys,re
t=str.maketrans('sztdnmrljkcgqfvpb','00112345677778899','aehiouwxy\n')
for s in open('f'):re.sub('sh|ch','j',s).translate(t)!=sys.argv[1] or print(s,end='')

รุ่นที่อ่านได้:

import sys, re

table = str.maketrans('sztdnmrljkcgqfvpb', '00112345677778899', 'aehiouwxy\n')

for line in open('f'):
    line = re.sub('sh|ch', 'j', line)
    if line.translate(table) == sys.argv[1]:
        print(line, end='')

รหัสนี้ใช้ประโยชน์จากความจริงที่thซ้ำซ้อน (เพราะมันจะจับคู่กับหมายเลขเดียวกันtและhเป็นตัวอักษรรอง)

maketransฟังก์ชันสแตติกสร้างตารางการแมปอักขระของอาร์กิวเมนต์แรกกับอาร์กิวเมนต์ที่สองและอักขระของอาร์กิวเมนต์ที่สามถึงNone(ซึ่งจะส่งผลให้อักขระเหล่านั้นถูกลบ)

translateรหัสสุดท้ายอาจจะทำไม่กี่ไบต์สั้นโดยการสร้างตารางเป็นอาร์กิวเมนต์โดยตรงของ


คุณสามารถบันทึกสองสามไบต์โดยใช้อินพุต () แทน sys.argv [1] และ '[sc] h' สำหรับนิพจน์ปกติของคุณ
swstephe

@swstephe ขอบคุณสำหรับคำติชม แต่ฉันไม่คิดว่าinput()จะสามารถใช้งานได้เพราะมันถูกเรียกว่าภายในลูป นอกจากนี้ regex ที่คุณแนะนำมีความยาวเท่ากับที่ฉันใช้อยู่ (5 ไบต์)
ekhumoro

ฉันกำลังคิดบางอย่างเช่น "z, t = input (), str.maketrans ... " จากนั้นใช้ z แทน sys.argv โอเคฉันคิดว่า regex ของฉันคือ 4 ไบต์
swstephe

2

sed, paste, grep, cut - 109

sed -e 's/[sc]h/6/g;s/[aehiouwxy]//g;y/sztdnmrljkcqgfvpb/00112345677778899/' w|paste w -|grep " $1$"|cut -f1

ใช้ไฟล์ "w" แปลงแต่ละคำให้เป็นตัวเลขวางกลับไปที่เดิม grep สำหรับตัวเลขและคืนคำที่ตรงกัน โปรดทราบว่าช่องว่างหลังใบเสนอราคาหลังจาก grep เป็นแท็บตัวคั่นเริ่มต้นของ

ฉันรู้ว่า Perl เป็นวิธีข้างหน้าเพียงแค่ต้องการรุ่นเปลือกที่ดีกว่าเป็นตัวอย่าง

โอ้ใช่ส่วน $ 1 หมายความว่าสิ่งนี้ควรจะถูกเรียกใช้จากเชลล์สคริปต์ (เชลล์ส่วนใหญ่ควรใช้งานได้) ดังนั้นจึงต้องใช้อาร์กิวเมนต์บรรทัดคำสั่ง


ฉันกำลังคิดที่จะแปลงคำตอบของฉันให้บริสุทธิ์sedเพื่อหลีกเลี่ยงการเปิดและ@ARGVค่าใช้จ่ายของ Perl แต่การขาดช่วงและฟังก์ชั่นการลบในการy///แบ่งมัน sedน่าแปลกที่ว่าแม้จะมีตัวแปรไม่มีคุณสามารถแสดงตรรกะของตัวเองโดยตรงใน นี่คือวิธีแก้ปัญหา 92 ของฉัน:sed -e'h;s/[sc]h/6/g;y/sztdnmrljkcqgfvpb/00112345677778899/;s/[^0-9]*//g;T;s/^$1$//;x;t;d' f
nutki

ดูเหมือนว่าจะทำงานทำไมไม่ให้คำตอบ?
swstephe

1

Bash + coreutils, 216

sed -n "$(sed 's/[aeiouwxy]//g
:l
s/\([^sc]\)h/\1/g
tl'<w|grep -nf <(eval printf '%s\\n' `sed 's/0/{s,z}/g
s/1/{t,th,d}/g
y/2345/nmrl/
s/6/{j,sh,ch}/g
s/7/{k,c,g,q}/g
s/8/{f,v}/g
s/9/{p,b}/g'<<<$1`)|sed s/:.\*/p/)" w
  • รายการคำศัพท์ในไฟล์ที่เรียกว่า w
  • ด้านในสุดsedจะแทนที่ตัวเลขด้วยการแทนที่ที่เป็นไปได้
  • การeval printfใช้ shell brace expansion เพื่อขยายการทดแทนที่เป็นไปได้ทั้งหมด
  • บรรทัดที่สองsedในบรรทัดที่ 1 จะลบaeiouwxyและh(เมื่อไม่นำหน้า[sc]) จากรายการคำ
  • grep พิมพ์ข้อมูลที่ตรงกันทั้งหมดพร้อมหมายเลขบรรทัด
  • เนื่องจากเราได้ออกปล้นaeiouwxyและhจากรายการคำสุดท้ายsedผลัดผลการ grep (ที่หมายเลขบรรทัดของแต่ละการแข่งขัน) ไปยังอีกsedแสดงออกซึ่งการประมวลผลโดยนอกสุดsedที่จะเปิดเผยคำที่เป็นไปได้ทั้งหมดจาก WordList

เอาท์พุท:

ไฟล์รายการคำถูกระบุเป็น ARG บรรทัดคำสั่งตามด้วยหมายเลขเพื่อช่วยในการจำ:

ubuntu@ubuntu:~$ ./numzi.sh 99
bob
pop
bop
bopy
boppy
$ ./numzi.sh 0123456789
stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb
$ 

@ Calvin'sHobbies Done
Digital Trauma

ดูเหมือนว่าคุณจะลืมอัปเดตตัวอย่างของคุณ
งานอดิเรกของ Calvin

-1

tr, sed, grep, xargs, sh, 77

tr 0123456789 ztnmrljkfp|sed 's/ */[aehiouwxy]*/g'|xargs sh -c 'grep -x $0 f'

คาดว่าตัวเลขที่อยู่ใน stdin fและรายการคำที่ควรจะเก็บไว้ในแฟ้ม

ไม่ใช้การแทนที่ทั้งหมด (1 จะเป็น z เสมอ, 7 จะเป็น k เสมอ) ดังนั้นจึงอาจเรียกว่าโซลูชันแบบขี้เกียจ แต่พบว่าช่วยในการจำอย่างน้อยหนึ่งหมายเลขสำหรับหมายเลข 95 ใน [1-100]


3
คำถามถามว่าคุณพบคำที่ตรงกันทั้งหมดในรายการคำ คุณไม่สามารถทำให้1เสมอzหรือ7เสมอkเสมอสิ่งนี้ไม่ถูกต้อง
งานอดิเรกของ Calvin

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