dc , 47 ไบต์
dc , 48 ไบต์
นอกจากนี้ยังทุบตีสาธารณูปโภค + Unix, 29 ไบต์
dc (47 ไบต์):
1sb[_1sb]s zz?sdlb*sc[pld+lnx]sl[dlb*lcr<l]dsnx
ลองออนไลน์!
โปรดทราบว่าจะต้องป้อนตัวเลขลบด้วยเครื่องหมายขีดล่างแทนเครื่องหมายลบเพราะนั่นคือวิธีที่ dc ยอมรับอินพุตตัวเลข ดังนั้นเขียนเช่น _5 แทน -5
dc ไม่สามารถอ่านอักขระหรือสตริงอินพุตในตัวแปรและประมวลผล (มีคำอธิบายโดยละเอียดด้านล่าง) แต่ฉันพบวิธีแก้ไขสองวิธีนี้:
แก้ปัญหา dc 47 ไบต์ทำงานในการป้อนข้อมูลที่มี argument1 และ argument2 กลับมีช่องว่างเป็นตัวคั่น ดังนั้นการนับจาก 1 ถึง (แต่ไม่รวม) 10 ในขั้นตอนที่ 3 จะถูกป้อนเป็น:
< 1 10 3
หากไม่สามารถเปลี่ยนลำดับของข้อโต้แย้งได้ฉันก็ให้วิธีแก้ปัญหาแบบ48 ไบต์ซึ่งเก็บลำดับเดิมของข้อโต้แย้ง อันนี้ใช้zz
เป็นตัวคั่นระหว่างอาร์กิวเมนต์ ดังนั้นการนับจาก 1 ถึง (แต่ไม่รวม) 10 ในขั้นตอนที่ 3 อีกครั้งจะใช้บรรทัดอินพุตต่อไปนี้:
1zz<zz10zz3
ในที่สุดความคิดเดียวกันผลผลิตแก้ปัญหาทุบตี 29 ไบต์
รายละเอียดเกี่ยวกับการขาดการประมวลผลสตริงของ dc และวิธีที่โปรแกรมนี้เกี่ยวข้องกับสิ่งนั้น:
การจัดการปัญหานี้ใน dc นั้นเป็นเรื่องยุ่งยากเพราะ dc ไม่ยอมรับสตริงหรืออักขระอินพุตเหมือนกับภาษาส่วนใหญ่ เมื่อ dc อ่านสตริงอินพุตสตริงนั้นจะรันสตริงนั้นทันทีเป็นโปรแกรม dc (แมโคร) จากนั้นละทิ้งสตริง คุณไม่สามารถเก็บอักขระของสตริงในหน่วยความจำและประมวลผลในภายหลังหรือด้วยวิธีอื่นใด สิ่งนี้รบกวนความต้องการที่จะมี '<' หรือ '>' ในอินพุต
ฉันจะแสดงสองวิธีรอบนี้ ในโซลูชันด้านบน (47 ไบต์) เราสลับลำดับของอินพุตสองตัวแรก ตัวคั่นอินพุตคืออักขระเว้นวรรค ตัวอย่างเช่นหากต้องการนับตั้งแต่ 1 ถึง (แต่ไม่รวม) 10 ในขั้นตอนที่ 3 คุณต้องป้อนข้อมูล
< 1 10 3
นี่คือแนวคิดเบื้องหลังโซลูชันนี้:
แมโครใน dc ถูกเก็บไว้ในรีจิสเตอร์และรีจิสเตอร์มีชื่ออักขระเดียว ฉันเก็บแมโครไว้ในรีจิสเตอร์ที่มีชื่อเป็นเพียงอักขระเว้นวรรค
โปรแกรมทำงานโดยกด 0 และ 1 บนสแต็กก่อนรับอินพุต จากนั้นเมื่ออินพุตถูกเรียกใช้เป็นโปรแกรม dc (ซึ่งเป็นสิ่งที่ dc ทำกับบรรทัดอินพุต) อักขระ '<' หรือ '>' จะถูกเรียกใช้งานเป็นคำสั่งซึ่งเป็นการเรียกใช้แมโครตามเงื่อนไขของแมโครที่มีชื่อคือ ถ่านตัวถัดไปหลังจาก '<' หรือ '>' โดยเฉพาะไอเท็มสองอันดับแรกบนสแต็ก หากรายการแรกที่ผุดคือ <(ตามลำดับ>>) รายการที่สองที่ผุดมาโครที่ระบุจะถูกดำเนินการ อักขระถัดไป (หลัง '<' หรือ '>') เป็นช่องว่างดังนั้นมาโครที่เราเก็บไว้ในรีจิสเตอร์ที่มีชื่อคือ space char นั้นเป็นตัวที่ถูกเรียกใช้งานถ้าเงื่อนไขมีอยู่ แต่เราได้ผลัก 0 และ 1 ไปที่สแต็กดังนั้นไอเท็มแรกที่ผุดคือ 1 และไอเท็มที่สองที่ผุดคือ 0 ดังนั้น แมโครจะถูกดำเนินการเฉพาะในกรณีที่การทดสอบตามเงื่อนไขคือ> ไม่ใช่ < สิ่งนี้ช่วยให้เราสามารถแยกความแตกต่างระหว่าง '<' และ '>' ในอินพุต
รายการที่เหลือในบรรทัดเป็นเพียงตัวเลขและ dc จะกดตัวเลขเหล่านั้นตามลำดับบนสแต็ก
นี่คือคำอธิบายโดยละเอียด ส่วนใหญ่แล้วตัวแปรการนับ (i ใน pseudocode ในคำแถลงปัญหา) จะถูกเก็บไว้ที่ด้านบนสุดของสแต็ก
1sb Store 1 in register b. (b will end up being 1 for '<', and -1 for '>').
[_1sb]s Note that there is a space after the second s. So the space char is the name of a macro which stores -1 in b.
z Push 0 on the stack.
z Push 1 on the stack.
? Accept input in the format above. This will:
- Store 1 or -1 in b, depending on whether you've typed "<" or ">"
- Push each of the three numbers in turn on the stack.
sd Save the increment in register d.
lb*sc Save either limit or -limit in register c, depending on whether the input started with "<" or ">".
[pld+lnx]sl Define a macro called l which is the body of our loop:
- Prints the top of the stack
- Adds the increment to the top of the stack.
- Calls macro n (the loop test).
[dlb*lcr<l]dsn Define a macro called n which is the test of the loop:
It checks to see if i (at the top of the stack) times b is less than c; if so, it calls macro l (looping back).
x Execute the loop test macro initially (a while loop needs to have a test at the top before entering the loop the first time).
ในทางกลับกัน OP ระบุไว้:
Input can be in one-line using any format "a/b/c/d" or "a,b,c,d" etc.
ดังนั้นอาจไม่ถูกต้องที่จะเปลี่ยนคำสั่งซื้อและต้องการ b ก่อน a ในอินพุท
นี่คือทางเลือกที่เก็บ a, b, c และ d ตามลำดับดั้งเดิม เราได้รับอนุญาตให้ใช้ตัวคั่นใด ๆ ฉันจะใช้ zz เป็นตัวคั่น ดังนั้นการนับตั้งแต่ 1 ถึง (แต่ไม่รวม) 10 ในขั้นตอนที่ 3 จะถูกป้อนเป็น:
1zz<zz10zz3
โปรแกรมใหม่ซึ่งมีอินพุตที่คั่นด้วย zz คือ
dc (48 ไบต์):
1sb[_1sb]sz?sdiilb*sci[pld+lnx]sl[dlb*lcr<l]dsnx
นี่คือหนึ่งไบต์ยาวกว่าโซลูชันแรก 47 ไบต์
ลองใช้เวอร์ชันที่คั่นด้วย zz ออนไลน์!
โดยส่วนตัวแล้วฉันคิดว่าการ< 1 10 3
จัดรูปแบบคำสั่งซื้อที่แตกต่างนั้นมีความสำคัญกับปัญหามากขึ้น แต่อาจ1zz<zz10zz3
ตรงกับข้อกำหนดทางเทคนิคที่เกิดขึ้นจริง
คุณอาจจะได้คำตอบที่สั้นกว่านี้หากคุณอนุญาตให้ตัวคั่นที่แตกต่างกันระหว่างอาร์กิวเมนต์อินพุตที่ต่างกัน แต่ฉันไม่คิดว่านั่นเป็นจิตวิญญาณของปัญหา
ยูทิลิตีBash + Unix ขนาด 29 ไบต์
คุณสามารถเปลี่ยนแนวคิดพื้นฐานข้างต้นเป็นโปรแกรมทุบตี (ซึ่งเรียก dc); สิ่งนี้จะหลีกเลี่ยงปัญหาทั้งหมดที่มี "<" และ ">" และยังช่วยให้การจัดการพารามิเตอร์ตัวเลขต่าง ๆ ได้ง่ายขึ้นดังนั้นจึงมีความยาวเพียง 29 ไบต์เช่นเดียวกับ @ zeppelin's bash + bc answer
รุ่นทุบตี (29 ไบต์):
dc -e[p$4+d$3r$2l]sl$1d$3r$2l
ลองใช้เวอร์ชั่นทุบตีออนไลน์!
นี่คือคำอธิบายว่าโปรแกรม dc ภายในโปรแกรม bash ทำงานอย่างไร:
ค่าของ i ถูกเก็บไว้ที่ด้านบนสุดของสแต็กเกือบตลอดเวลา
[ Start of macro (i is at the top of the stack). This macro will be called l.
p Print i
$4+ i += (4th argument)
d Duplicate i at the top of the stack.
$3 Push the 3rd argument onto the stack.
r Swap the top two items on the stack, so i is at the top and arg3 is second
$2l $2 is "<" or ">", causing the top two items to be popped from the stack, and macro l is then called (effectively looping back) if i < arg3 or i > arg3, respectively.
]sl End of macro definition; store macro in register l.
$1 Push argument 1 onto the stack (i = 1st argument).
d$3r$2l Just as above, call macro l if i < arg3, or i > arg3, depending on whether arg2 is "<" or ">"