หมายเลขนั้นใน Shortlex คืออะไร


15

คอมพิวเตอร์ส่วนใหญ่เก็บจำนวนเต็มเป็นเลขฐานสอง แต่ส่งออกเป็นทศนิยม อย่างไรก็ตามทศนิยมเป็นเพียงตัวแทนเดียวเราเพิ่งพบว่าสะดวก

ความท้าทายนี้คือการเขียนโค้ดบางส่วนเพื่อส่งออกค่าจำนวนเต็ม ทศนิยมแบบสั้น

นั่นอะไร?
http://en.wikipedia.org/wiki/Shortlex_order

Shortlex ใช้ความยาวของลำดับของตัวเลขเป็นตัวบ่งชี้หลักของค่า ลำดับเริ่มต้นจากสตริงว่างแทนศูนย์คือ ...

ε,0,1,...,8,9,00,01,...98,99,000,001,...,998,999,0000,...

(คิดถึงคอลัมน์ Excel แต่ใช้เฉพาะเลขทศนิยมเท่านั้น)

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

ค่าทดสอบ:

0 → "" (สตริงว่าง)
1 → "0"
10 → "9"
11 → "00"
42 → "31"
100 → "89"
800 → "689"
1060 → "949"
10270 → "9159"
100501 → "89390"


2
มันอาจจะเป็นสิ่งสำคัญที่จะต้องทราบว่าลำดับ19, 20, 21, 22ในแผนที่ทศนิยมไปยัง08, 09, 10, 11ใน shortlex นั่นเป็นเหตุผลที่ฉันใช้สับสนว่า100 -> 89!
Sean Latham


6
โปรดทราบว่าสิ่งที่คุณกำลังเรียก "ทศนิยมแบบสั้น" ของตัวเลขนั้นยังมีตัวเลขฐานสิบ bijectiveด้วยสัญลักษณ์ {0,1,2,3,4,5,6,7,8,9} ทดแทนสำหรับ ตัวเลขปกติ {1,2,3,4,5,6,7,8,9, A} เช่น 2014 ในเครื่องหมายฐานสิบ bijective ปกติคือ 1A14 และในทศนิยมทศนิยมเป็น 0903
res

คำตอบ:


34

JavaScript (ES6) 42 74

n=>(n-~(n+'').replace(/./g,8)+'').slice(1)

ทดสอบในคอนโซล FireFox

;[0,1,10,11,42,100,800,1060,10270,100501]
.forEach(x => console.log(x +" -> '" + S(x) + "'"))

เอาท์พุต

0 -> ''
1 -> '0'
10 -> '9'
11 -> '00'
42 -> '31'
100 -> '89'
800 -> '689'
1060 -> '949'
10270 -> '9159'
100501 -> '89390'

ฉันคิดยังไงกับเรื่องนี้?

กำหนดตัวเลขคงที่ลำดับเอาท์พุทเป็นไปได้ง่ายขึ้นดังนั้นจึงมีเดลต้าคงที่ระหว่างอินพุตและเอาต์พุต ไปดูกัน:

  1..10 -> 0..9 (delta -1)
 11..110 -> 00..99 (delta -11)
111..1110 -> 000..999 (delta -111) mmm there's a pattern here...

แต่ 0s ชั้นนำนั้นยากที่จะจัดการดังนั้นฉันจึงมีเคล็ดลับมาตรฐานเพิ่มตัวเลขตัวแรกและ modulo ทำงาน (นั่นคือตัดตัวเลขหลักแรกในเอาต์พุต) จากนั้น -1-> +9, -11 -> +89, -111 -> +889 เป็นต้น
ขั้นตอนสุดท้าย: ฉันไม่สนใจว่าหลักแรกคืออะไรดังนั้นจึงไม่จำเป็นต้องตรวจสอบว่าหมายเลข iinput เป็น <หรือ> มากกว่า 111 ... (โดยสุจริตฉันพบสิ่งนี้ด้วยการลองผิดลองถูก)

ทดสอบ

var F=
n=>(n-~(n+'').replace(/./g,8)+'').slice(1)

function update()
{
  var i=+I.value
  O.textContent = F(i)
}


update()
<input id=I value=99 type=number oninput='update()'><pre id=O></pre>


8
ฉันไม่รู้ว่าทำไมงานนี้
Martin Ender

ทำไมคุณถึงทำn-~(n+'')แทนที่จะเป็นแค่n-~n?
Claudiu

@ Claudiu มันคือ(n+'').replace(...)แทนที่การทำงานกับสตริงไม่ใช่ตัวเลข
edc65

@ edc65: อ๊ะใช่เพิ่งจับได้แล้ววงเล็บของฉันไม่ตรงกัน วันนี้มันยอดเยี่ยมมาก
Claudiu

3
@Dennis รู้สึกฟรีที่จะพอร์ต คุณชนะแล้ว
edc65

13

Marbelous 177 173 170

@0@6000000@5
}0&0&0&0&0
>0@6&3
\\--\/&2
@0/\@4\/&1!!
@4@1..@2@5@3
IIIIIIIIIIII
FF&1FF&2FF&3
@1OO@2OO@3OO
:I
}1..}10001F7
=9&1++..&1&0
&0}0&1&0{1{1
{>\/{0//
:O
}0
+Z
+C
{0

ใช้งานได้กับค่าต่ำกว่า 256 เท่านั้นเนื่องจาก Marbelous เป็นภาษา 8 บิต

มันทำงานอย่างไร

Marbelous เป็นภาษา 2D ที่มีค่าเป็นตัวแทนของหินอ่อน 8 บิตที่ตกลงมาหนึ่งเซลล์ในแต่ละขีด โปรแกรม Marbelous นี้ประกอบด้วย 3 บอร์ด เริ่มจากสิ่งที่ง่ายที่สุด:

:O
}0
+Z
+C
{0

:O คือชื่อของบอร์ด (เพื่อความถูกต้อง O คือชื่อและ: บอกการตีความว่าบรรทัดนี้เป็นชื่อโดยให้ชื่อบอร์ดแก่บอร์ดอื่น ๆ สามารถโทรหาพวกเขาได้ }0เป็นอุปกรณ์ป้อนข้อมูลนี้สามารถมองเห็นเป็น อาร์กิวเมนต์ของฟังก์ชั่นนี้เซลล์นี้จะถูกแทนที่ด้วย input หินอ่อน (ค่า) เมื่อฟังก์ชั่นได้รับการเรียก +Zเพิ่ม 35 หินอ่อนใด ๆ ที่ผ่านมันและช่วยให้มันผ่านไป+Cทำเหมือนกัน แต่เพิ่มเพียง 12 {0เป็นเซลล์เอาท์พุท เมื่อหินอ่อนมาถึงเซลล์นี้ฟังก์ชั่นจะออกและส่งกลับค่าในอุปกรณ์ส่งออกนี้

ดังนั้นทั้งหมดเข้าด้วยกันบอร์ดนี้ใช้หนึ่งค่าแล้วเพิ่ม 47 ลงไป สำหรับเรานี่หมายความว่ามันจะเปลี่ยนหมายเลขหลักเดียวให้เป็นรหัส ascii ของหลัก -1 (ซึ่งแน่นอนว่าจะใช้ได้สำหรับ 10)

:I
}1 .. }1 00 01 F7
=9 &1 ++ .. &1 &0
&0 }0 &1 &0 {1 {1
{> \/ {0 //

กระดานนี้ดูซับซ้อนกว่านี้เล็กน้อย คุณควรระบุ:Iชื่อบอร์ดได้และเห็นอุปกรณ์อินพุตและเอาต์พุตบางตัว คุณจะพบว่าเรามีสองอุปกรณ์ป้อนข้อมูลที่แตกต่างกันและ}0 }1นี่หมายความว่าฟังก์ชั่นนี้ใช้ 2 อินพุต คุณจะสังเกตเห็นว่ามีสองกรณีของ}1อุปกรณ์ เมื่อเรียกใช้ฟังก์ชันทั้งสองเซลล์เหล่านี้จะมีค่าเท่ากัน }0อุปกรณ์ป้อนข้อมูลโดยตรงดังกล่าวข้างต้น\/อุปกรณ์นี้ทำหน้าที่เป็นถังขยะและลบหินอ่อนใด ๆ ที่อยู่กับมันทันที

ลองมาดูสิ่งที่เกิดขึ้นกับหนึ่งในหินอ่อนที่ใส่ไว้ในบอร์ดโดย}1อุปกรณ์อินพุต:

}1
=9 &1
&0
{>

มันจะล้มลงบนเห็บตัวแรกและกด=9อุปกรณ์ สิ่งนี้จะเปรียบเทียบค่าของหินอ่อนกับ 9 และทำให้หินอ่อนตกลงหากคำสั่ง=9ประเมินผ่าน หินอ่อนจะถูกผลักไปทางขวาถ้าไม่ &0และ&1เป็นตัวประสาน พวกเขายึดมั่นกับหินอ่อนที่ตกลงมาจนกระทั่งพวกเขาอื่น ๆ&nที่เต็มไปด้วยเช่นกัน ตามที่คุณคาดหวังสิ่งนี้จะทำให้เกิดพฤติกรรมที่แตกต่างกันในส่วนอื่น ๆ ของกระดาน

}1 00 01 F7
++ .. &1 &0
&1 &0 {1 {1
{0 //

ถ้าฉันบอกคุณว่า++เป็นตัวเพิ่มคุณควรจะสามารถบอกได้ว่าตัวประสานต่าง ๆ นั้นจะถูกเติมด้วยอะไร ด้านซ้าย&1จะมีค่าอินพุต}1+ 1 &0ถัดจากนั้นจะมี 0 ( 00เป็นตัวอักษรภาษาแสดงเป็นเลขฐานสิบหก) อันที่สอง&1จะมีค่า 1 และด้านขวา&0ถูกเติมด้วย an F7ซึ่งลบ 9 จากค่าเนื่องจากการเพิ่มใน Marbelous คือ modulo 256

// เป็นอุปกรณ์ดันที่ผลักหินอ่อนไปทางซ้ายแทนที่จะปล่อยให้มันตกลงมา

การรวมสิ่งนี้เข้าด้วยกันจะช่วยให้คุณได้สิ่งนี้: หากหินอ่อนใน}1เท่ากับ 9 &0ซิงโครไนเซอร์จะถูกเติมเต็ม สิ่งนี้จะทำให้ค่า 0 ตกอยู่ใน{0เอาต์พุตและF7(หรือ -9) ลงใน{1เอาต์พุต หาก}1ไม่ใช่ 9 {0จะถูกเติมด้วย}1+ 1 และ{0จะประกอบด้วย 1 นอกจากนี้ยังมี{>อุปกรณ์นี่เป็นเอาต์พุตพิเศษที่ส่งออกหินอ่อนที่อยู่ถัดจากบอร์ดแทนที่อยู่ด้านล่าง สิ่งนี้จะได้รับการเติม}1ถ้ามันเท่ากับ 9

@0 @6 00 00 00 @5
}0 &0 &0 &0 &0
>0 @6 &3
\\ -- \/ &2
@0 /\ @4 \/ &1 !!
@4 @1 .. @2 @5 @3
II II II II II II
FF &1 FF &2 FF &3
@1 OO @2 OO @3 OO

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

@0 @6
}0 &0
>0 @6
\\ --
@0 /\ @4

ดังนั้นค่าอินพุต (อินพุตบรรทัดคำสั่งตั้งแต่นี่คือบอร์ดหลัก) เริ่มต้นที่เซลล์ที่สองจากด้านบนซึ่ง}0เป็นที่ตั้ง มันจะล้มลงและไปถึง>0อุปกรณ์ซึ่งเป็นอุปกรณ์เปรียบเทียบอีกเครื่องหนึ่ง หินอ่อนที่มีขนาดใหญ่กว่า 0 จะตกลงมาหินอ่อนอื่น ๆ จะถูกผลักไปทางขวา (เนื่องจากตัวแปรของ Marbelous นั้นไม่ได้รับการลงนามมีเพียง 0 เท่านั้นที่ถูกผลักไปทางขวา) หินอ่อนที่มีค่าเป็นศูนย์นี้จะเข้าสู่@6อุปกรณ์ นี่คือพอร์ทัลและส่งหินอ่อนไปยังพอร์ทัลอื่นที่เกี่ยวข้องในกรณีนี้อยู่ด้านบน จากนั้นหินอ่อน 0 จะไปถึงตัว&0ซิงโครไนซ์และทริกเกอร์บางสิ่งที่อื่น

หากหินอ่อนไม่ใช่ 0 มันจะตกลงมาได้รับการเบี่ยงเบนไปทางขวาโดยการ\\ยิง--ซึ่งจะทำให้มันลดลงทีละหนึ่งแล้วก็ตกลงไป/\ที่ cloner อุปกรณ์นี้นำหินอ่อนและส่งสำเนาหนึ่งชุดไปทางขวาและอีกชุดหนึ่งไปทางซ้าย ส่วนที่เหลือจะถูกนำขึ้นไปที่อื่น@0ซึ่งหินอ่อนจะผ่านลำดับเดียวกันอีกครั้ง ส่วนที่เหลือจะถูกนำไปที่อื่น สิ่งนี้ทำให้เรามีลูปซึ่งลดอินพุตบรรทัดคำสั่งหนึ่งครั้งต่อหนึ่งลูปและทริกเกอร์พฤติกรรมบางอย่างในทุกลูปจนกว่าจะถึง 0 จากนั้นจะทริกเกอร์พฤติกรรมอื่น ๆ

ลองมาดูสิ่งที่เกิดขึ้นกับหินอ่อนที่ผลักเข้าไป@4ในแต่ละวง

@4 @1 .. @2 @5 @3
II II II II II II
FF &1 FF &2 FF &3
@1 OO @2 OO @3 OO

มี 3 ตัวอักษรภาษาที่นี่ ( FF) ซึ่งจะตกอยู่ในพอร์ทัลทันที พอร์ทัลเหล่านี้จะนำพวกเขาไปยังIIอุปกรณ์สามอย่าง IIหมายถึงบอร์ดที่:Iเรากำหนดเพิ่มเติมลงไปในไฟล์ เนื่องจาก:Iมีอุปกรณ์อินพุต 2 ชนิดที่แตกต่างกันจึงมีการนำเสนอบนบอร์ดอื่นซึ่งต้องมีความกว้าง 2 เซลล์ เนื่องจากเรามี 6 เซลล์ที่มีIIเราบอกว่าเรามีฟังก์ชั่นนี้ 3 ตัวบนกระดาน

FF(หรือ 256 หรือ -1 ถ้าคุณจะ) หินอ่อนจะนั่งในเซลล์ป้อนข้อมูลของ:Iฟังก์ชั่นรอจนกว่าจะมีการป้อนข้อมูลพอ STO หินอ่อนเริ่มฟังก์ชัน (อีกหนึ่งที่มี) นั่นคือสิ่งที่@4พอร์ทัลเข้ามาสำเนาของอินพุตบรรทัดคำสั่งที่ลดลงจะอยู่ตรงนั้นในแต่ละลูป นี่จะทำให้:Iกระดานซ้ายสุด เริ่มต้นด้วยค่า 256 (หรือ -1) และสิ่งที่อินพุตบรรทัดคำสั่งคือ -1 หินอ่อนซ้ายจะถูกใส่ลงไปใน}0อุปกรณ์ของคณะกรรมการและหนึ่งที่เหมาะสมลงใน:I }1หากคุณจำได้ว่าบอร์ดนี้ทำอะไรคุณจะสามารถบอกได้ว่าผลลัพธ์นี้คืออะไร มันจะเอาท์พุทเวอร์ชั่นที่เพิ่มขึ้นของอินพุตด้านขวาบนเอาต์พุตด้านซ้าย (และเปลี่ยนเป็น 9 เป็น 0 ไม่ใช่ 10) และเอาต์พุตทั้ง 1 หรือ -9 ทางด้านขวา

ค่าที่เพิ่มขึ้นจะถูกนำกลับไปที่เซลล์ป้อนข้อมูลด้านขวาโดยพอร์ทัลและค่าด้านขวาจะอยู่ในซิงโครไนซ์ หากมีการซิงโครไนซ์ที่ถือหินอ่อนอยู่หินอ่อนสองลูกจะชนกัน การชนกันของหินอ่อนจะถูกรวมเข้าด้วยกันโมดูโล 256 ดังนั้นค่าในซิงโครไนเซอร์จะทำการ folowing: พวกมันเริ่มว่างแล้วจึงหันไปหา 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, และ 1 อีกครั้ง (ตั้งแต่ 247 เพิ่ม modulo 256)

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

คุณอาจจำได้ว่า:Oฟังก์ชั่นเปลี่ยนค่าเป็นค่า ascii ของตัวเลขที่แสดงถึงค่า -1 ผลลัพธ์ของOOเซลล์เหล่านี้จะหลุดออกจากบอร์ดซึ่งจะพิมพ์ ascii chars ที่สอดคล้องกันไปยัง STDOUT

00 00 00 @5
&0 &0 &0
&3
\/ &2
   \/ &1 !!
      @5

ดังนั้นจะเกิดอะไรขึ้นเมื่อหินอ่อนอินพุตบรรทัดคำสั่งถึง 0 และเติม&0ข้อมูลให้ตรงกัน? ดีหินอ่อนมูลค่า 0 สองสามตกลงมาและทริกเกอร์สาม synchronizers ที่ถือหลัก (+ 1) ของหมายเลข shortlex ที่ด้านล่างของบอร์ด &3ได้รับการเรียกครั้งแรกเพราะมันมีหลักที่สำคัญที่สุดแล้วมาตามมาด้วย&2 &1หินอ่อนนี้จะถูกเคลื่อนย้ายไปยัง@5อุปกรณ์อื่นก่อนที่จะกระแทก!!เซลล์ในที่สุดซึ่งจะยุติบอร์ด


4
ดูเหมือนว่านี่อาจเป็นรหัส Perl ที่ถูกต้องเช่นกัน
Doorknob

12

CJam, 14 11 ไบต์

l40f-Ab)s1>

ลองออนไลน์

มันทำงานอย่างไร

วิธีนี้ขึ้นอยู่กับคำตอบของ edc65 (ด้วยการอนุญาตอย่างชัดเจน ):

" Read a line L from STDIN. ";

l

" edc65's answer now forms an integer N by replacing each digit in L by an 8 and computes
  L - ~N = L + N + 1. Instead of adding L and N, we subtract 40 from each char code of L.
  Since the char code of the digit `D` is `D + 48`, this basically adds 8 to each digit.  ";

40f-

" Turn the resulting array into an integer by considering its elements a base 10 number.
  This is implemented as A ↦ A[-1] + 10 * A[-2] + 100 * A[-3] + ⋅⋅⋅, so it won't choke
  on digits greater than the base.                                                        ";

Ab

" Increment the integer on the stack to complete the calculation of L + N + 1.            ";

)

" Push the integers string representation and discard its first character.                ";

s1>

ตัวอย่างการวิ่ง

$ for i in 0 1 10 11 42 100 800 1060 10270 100501
> do echo $i: $(cjam <(echo 'l40f-Ab)s1>') <<< $i)
> done
0:
1: 0
10: 9
11: 00
42: 31
100: 89
800: 689
1060: 949
10270: 9159
100501: 89390

1
นี่คือลามกอนาจาร
Claudiu

3
+1 เพื่อค้นหาวิธีย่อให้สั้นยิ่งขึ้น
edc65

6

Python 2 (38) (43)

f=lambda n:n*'_'and f(~-n/10)+`~-n%10`

ไม่มีการเปลี่ยนตัวอักขระเพียงแค่เลขคณิต

Ungolfed:

def f(n):
    if n==0: return ''
    else: return f((n-1)//10) + str((n-1)%10)

ฉันไม่มีเหตุผลที่ดีว่าทำไมการเรียกซ้ำฉันจึงพอดีกับรูปแบบนี้กับรายการค่า หากคุณเปลี่ยนn-1เป็นnคุณจะได้รับตัวเลขหลักปกติ

สำหรับการเล่นกอล์ฟฉันใช้~-nในการคำนวณที่n-1มีลำดับความสำคัญสูงกว่า/10หรือ%10ประหยัดจากการล้อเลียน n*'_'เป็นเพียงการผลิตสตริงว่างเมื่อn=0และสายอื่น ๆ ใด ๆ มิฉะนั้น '_'สามารถเป็นสตริงใด ๆ เพื่อการนี้


4

Ruby, 70 68 66 64 57 ไบต์

f=->n{i=-1;n-=10**i while n>=10**i+=1;i<1?'':"%0#{i}d"%n}

f[42]กำหนดฟังก์ชั่นที่จะเรียกว่าเหมือน นี่คือขั้นตอนวิธีแบบคร่าวๆ:

  • รักษา0แยกต่างหาก
  • ลบกำลังของ 10 จนกว่ากำลังต่อไปของ 10 ไม่พอดีกับหมายเลขอีกต่อไป
  • เปลี่ยนตัวเลขให้เป็นสตริงที่มีเลขศูนย์ที่ด้านซ้าย

เครดิตสำหรับแนวคิดของการใช้สตริงรูปแบบไปที่ Falko!


อีกทางเลือกหนึ่งโดยใช้วิธีการของ edc65:

f=->n{"#{n-~n.to_s.tr('^.',?8).to_i}"[1..-1]}

นั่นคือ45 ไบต์และฉันแค่รวมมันเพราะฉันไม่ได้ตีเขาด้วย ;)


แน่ใจ ฉันเดาว่าฉันจะไม่จับคุณด้วยรหัส Python ที่มีความยาวของฉัน ;)
Falko

@Optimizer ฉันแน่ใจว่ามีคนใช้วิธีการนี้ในภาษากอล์ฟที่พวกเขาได้รับต่ำกว่า 20 (ที่ถูกกล่าวว่าฉันไม่สามารถเข้าถึง 44 ใน Ruby กับวิธีการที่ ... ตอนนี้ที่ 45)
มาร์ติน Ender

2
@Optimizer ฉันไม่เห็นด้วย สำหรับผู้เริ่มต้น J และ APL ไม่ใช่ภาษาการเล่นกอล์ฟและชนะบ่อยเท่าที่ GolfScript และ CJam แต่ยิ่งไปกว่านั้นการเล่นกอล์ฟไม่ได้เกี่ยวกับเครื่องหมายถูกสีเขียว แต่เกี่ยวกับการตีการส่ง "ในลีกของคุณ" ถ้าฉันเขียนบทความ Ruby ที่เต้นได้ทั้งหมดยกเว้นภาษาทั้ง 4 ภาษาฉันมีความสุขมากเกี่ยวกับเรื่องนั้นและฉันไม่ต้องการให้คนเหล่านั้นถูกห้ามเล่นกอล์ฟในภาษาอื่น ๆ ในความเป็นจริงสนามกอล์ฟที่ฉลาดในภาษา "ปกติ" อย่าง edc นั้นมีแนวโน้มที่จะได้รับ upvotes มากกว่าการใช้ภาษากอล์ฟที่ไร้เดียงสา (แต่สั้นกว่า)
Martin Ender

3

Haskell, 67 ไบต์

n('9':x)='0':n x
n(c:x)=succ c:x
n""="0"
f x=reverse$iterate n""!!x

วิธีนี้โดยทั่วไปจะเพิ่ม 1 จำนวนครั้งที่กำหนดในสัญกรณ์ shortlex

การใช้งาน:

>f 9
"8"
>f 100
"89"

3

CJam, 16 ไบต์

li_)9*,{`1>}%_&=

ลองออนไลน์ ต้องการเวลาและหน่วยความจำอย่างน้อย O (n) ดังนั้นปล่อยให้ 100501 เป็นล่ามออฟไลน์ ...

มันทำงานอย่างไร

แนวคิดพื้นฐานที่อยู่เบื้องหลังวิธีการนี้คือการคำนวณทศนิยมอย่างน้อย N ตัวย่อตามลำดับและทิ้งทั้งหมดยกเว้น Nth ไม่ค่อยมีประสิทธิภาพ แต่สั้น

li                " Read an integer N from STDIN.                                   ";
  _)9*            " Push M := (N + 1) * 9.                                          ";
      ,           " Push A := [ 0 1 ... M - 1 ].                                    ";
       {   }%     " For each I ∊ A:                                                 ";
       {`1>}%     " Push its string representation and discard the first character. ";
             _&   " Remove duplicates from the resulting array.                     ";
               =  " Retrieve the Nth element.                                       ";

ตัวอย่างการวิ่ง

$ for i in 0 1 10 11 42 100 800 1060 10270 100501
> do echo $i: $(cjam <(echo 'li_)9*,{`1>}%_&=') <<< $i)
> done
0:
1: 0
10: 9
11: 00
42: 31
100: 89
800: 689
1060: 949
10270: 9159
100501: 89390

3

Bash + coreutils, 27 ไบต์

คำตอบที่ฉลาดของพอร์ต@ edc65พร้อมการปรับปรุงของ @ Dennis :

cut -b2-<<<$[$1-~${1//?/8}]

เอาท์พุท:

$ for n in 0 1 10 11 42 100 110 111 800 1060 1110 1111 10270 100501; do echo "./shortlex.sh $n = \"$(./shortlex.sh $n)\""; done
./shortlex.sh 0 = ""
./shortlex.sh 1 = "0"
./shortlex.sh 10 = "9"
./shortlex.sh 11 = "00"
./shortlex.sh 42 = "31"
./shortlex.sh 100 = "89"
./shortlex.sh 110 = "99"
./shortlex.sh 111 = "000"
./shortlex.sh 800 = "689"
./shortlex.sh 1060 = "949"
./shortlex.sh 1110 = "999"
./shortlex.sh 1111 = "0000"
./shortlex.sh 10270 = "9159"
./shortlex.sh 100501 = "89390"
$ 

คำตอบก่อนหน้า:

Bash + coreutils, 71 54 ไบต์

นี่เป็นวิธีที่แตกต่างกันเล็กน้อยในการทำ:

jot -w%x $1$1|tr 0-9a a0-9|grep -P ^\\d+$|sed $1!d 2>-
  • jot เอาท์พุทเพิ่มจำนวนเต็มเลขฐานสิบหก
  • tr แปลงสิ่งนี้เป็น (0,1, ... , 8,9, b, ... f, 0a, 00,01, ... , 99,9b, ... , ff, 0aa, ... , 000 , ... )
  • grep เพียงกรองทุกบรรทัดที่มีตัวเลขเพื่อให้ (0,1, ... , 8,9,00, ... , 99,000 .... )
  • sed ลบทั้งหมดยกเว้นบรรทัดที่ n
  • STDERR ถูกเปลี่ยนเส้นทางไปยังไฟล์ throwaway '-' เพื่อให้เราได้รับสตริงว่างเปล่าเมื่อผ่าน 0 (sedนับจำนวนบรรทัดเริ่มต้นที่ 1 ดังนั้นข้อผิดพลาดถ้าผ่าน 0)
  • เนื่องจากเรากำลังกรองตัวเลขด้วยgrepเราจึงต้องสร้างฐาน 11 จำนวนเต็มมากกว่าseq/ dcมากกว่าจำนวนอินพุต การทำซ้ำตัวเลขของ n นั้นเพียงพอแล้ว

โปรดทราบว่าเมื่อพิมพ์หมายเลขย่อให้seqดำเนินการสร้างตัวเลขต่อไป$1$1ซึ่งช้าโดยเฉพาะอย่างยิ่งสำหรับหมายเลขอินพุตที่ใหญ่กว่า - O (n²) ฉันคิดว่า เราสามารถเร่งความเร็วได้โดยการseqออกจากระบบทันทีหลังจากพิมพ์ที่ราคา 7 ไบต์:

jot -w%x $1$1|tr 0-9a a0-9|grep -P ^\\d+$|sed -n $1{p\;q} 2>-

ไม่มีข้อกำหนดความเร็วในคำถามดังนั้นฉันจะไปกับรุ่นที่สั้นกว่าสำหรับคำตอบหลักของฉัน


@Optimizer Nope: s='jot -w%x $1$1|tr 0-9a a0-9|grep -P ^\\d+$|sed $1!d 2>-'; echo ${#s}ลอง ฉันสงสัยว่าคุณอาจใช้ไพ ธ อนเพื่อวัดความยาวของสตริงซึ่งถือว่า "\\" เป็นอักขระตัวเดียว
Digital Trauma

2
คำตอบของฉันเปลี่ยนไปแล้ว แต่ถ้าฉันทำอะไรที่ชาญฉลาดในการแก้ไขครั้งแรกมันทั้งหมดโดยไม่ได้ตั้งใจ มันเป็นคำตอบที่ตรงจาก edc65 8 ของทั้งหมดของเขา ... - ตัวแปรเสริม$aดูเหมือนจะไม่จำเป็น; cut -b2-<<<$[$1-~${1//?/8}]ควรทำงานได้ดี
Dennis

1
@Dennis ขวาฉันเห็น ขอบคุณสำหรับคำแนะนำ!
Digital Trauma

2

Python 2 - 84, 70 66

n=input()
i=0
while n>=10**i:n-=10**i;i+=1
print"%%0%dd"%i%n*(i>0)

ทางเลือกวิธี (ความยาวเดียวกัน):

n=input()
k=len(`9*(n+1)/10`)
print"%%0%dd"%k%(n-int('1'*k))*(n>0)

ใช้สตริงรูปแบบฉลาด! ฉันหวังว่าคุณจะไม่รังเกียจถ้าฉันใช้มันเช่นกัน :)
Martin Ender

2

Python 3, 107 ตัวอักษร

สิ่งนี้ไม่ได้จบลงด้วยการชนะ แต่ฉันคิดว่ามันฉลาด:

def G():yield'';yield from(r+c for r in G()for c in'0123456789')
S=lambda n:list(zip(range(n+1),G()))[n][1]

ฉันกำหนดตัวกำเนิดสำหรับลำดับทั้งหมดใน 64 อักขระ น่าเสียดายที่ผมจะต้องไปผ่าน contortions ที่จะได้รับองค์ประกอบที่ n ของเครื่องกำเนิดไฟฟ้า ... S=lambda n:G()[n]ถ้าเดียวที่ฉันจะทำอย่างไร


2

Pyth , 12

อีกพอร์ตของคำตอบของ @ edc65 ซึ่งเป็นผู้ชนะที่ชัดเจน (IMO):

t`+hQv*l`Q\8

แพคเกจการทดสอบ (ขอบคุณ @DigitalTrauama):

$ for n in 0 1 10 11 42 100 110 111 800 1060 1110 1111 10270 100501; do echo "shortlex.pyth $n = \"$(pyth programs/shortlex.pyth <<< $n)\""; done
shortlex.pyth 0 = ""
shortlex.pyth 1 = "0"
shortlex.pyth 10 = "9"
shortlex.pyth 11 = "00"
shortlex.pyth 42 = "31"
shortlex.pyth 100 = "89"
shortlex.pyth 110 = "99"
shortlex.pyth 111 = "000"
shortlex.pyth 800 = "689"
shortlex.pyth 1060 = "949"
shortlex.pyth 1110 = "999"
shortlex.pyth 1111 = "0000"
shortlex.pyth 10270 = "9159"
shortlex.pyth 100501 = "89390"

คำอธิบาย:

Q = eval(input())             Implicit.
t`                            All but the first digit of
  +hQ                         Q+1 + 
   v                          eval(
    *l`Q                      len(repr(Q)) * 
     \8                       "8"

CJam vs Pyth; การต่อสู้ดำเนินต่อไป : P
Dennis

ฉันพยายามที่จะให้ Pyth ถูกยิงสำหรับความท้าทายนี้ แต่ฉันหาทางเปลี่ยน List เป็นจำนวนเต็มไม่ได้ (เช่น[8, 8, 9] -> 889) คุณจะทำอย่างไร
Dennis

@Dennis ในการรับจากรายการถึง int คุณต้องผ่านสายอักขระ jkจะเปลี่ยนรายการของคุณเป็นสตริงและvจะเปลี่ยนเป็นสตริง ดังนั้นvjk[8 8 9]จะให้หมายเลข 889
isaacg

โอเคขอบคุณ. น่าเศร้าที่การแปลงสตริงทำให้เทคนิคเป็นไปไม่ได้ ด้วย CJam / แปลงฐาน GolfScript, และ[2 -1] -> 19 [1 11] -> 21
เดนนิส

1
@Dennis Yeah เมื่อฉันเพิ่มการแปลงฐานเป็น Pyth จริง ๆ แล้วมันก็ใช้ได้ แต่ฉันยังไม่ได้
isaacg


1

Haskell , 57 ไบต์

((g=<<[0..])!!)
g 0=[""]
g n=[c:s|c<-['0'..'9'],s<-g$n-1]

ลองออนไลน์!

สร้างรายการหมายเลขย่อและดัชนีแบบไม่ จำกัด เพื่อหาคำตอบ g nสร้าง "รุ่น" ที่ n ของตัวเลขโดยการเติมตัวเลขถัดไปไว้ข้างหน้าของตัวเลขแต่ละตัวในรุ่นก่อนหน้า




0

เยลลี่ 5 ไบต์

ḃ⁵ịØD

ลองออนไลน์!

ฉันยังใหม่กับ Jelly มากดังนั้นหากคุณสามารถปรับปรุงได้โปรดแสดงความคิดเห็น!

คำอธิบาย:

ḃ⁵ịØD   Main link.
ḃ       Convert to bijective base ...
 ⁵      10.
  ị     Each number (1 - 10) is converted to the character at its index in the string...
   ØD   “0123456789” (digits)

(ตามความคิดเห็นของ res ข้างต้นปัญหาเทียบเท่ากับการแปลงจำนวนเป็นฐาน bijective 10)

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