แยกรายการหมายเลข unary ที่เซ็นชื่อ


16

โดยทั่วไปแล้วตัวเลขที่ไม่ใช่ตัวเลขจะแสดงเฉพาะจำนวนเต็มที่ไม่ใช่ค่าลบ แต่เราสามารถขยายตัวเลขเหล่านี้เพื่อแสดงจำนวนเต็มทั้งหมดดังนี้:

  • จำนวนเต็มบวก N ถูกแทนด้วย N 1:5 -> 11111
  • จำนวนเต็มลบ -N ถูกแทน0ด้วยตามด้วย N 1:-5 -> 011111
  • ศูนย์แสดงเป็น 0

จากนั้นเราสามารถแสดงรายการของตัวเลขเหล่านี้ได้อย่างชัดเจนหากเราใช้0เป็นตัวคั่น:

3,-2,0,1
111,011,0,1
111 0 011 0 0 0 1
11100110001

งานของคุณ: นำสตริงที่แสดงรายการของหมายเลขยูนารีที่ลงนามแล้วและแปลเป็นรายการของเลขทศนิยม

รายละเอียด

คุณอาจสมมติว่าการป้อนข้อมูลเป็นรายการที่สมบูรณ์ของหมายเลข unary ที่ลงนามแล้ว โดยเฉพาะอย่างยิ่งโปรแกรมของคุณจะไม่ต้องจัดการ 1) อินพุตว่างเปล่าหรือ 2) อินพุตที่ลงท้ายด้วยตัวคั่น

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

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

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

กรณีทดสอบ

1 -> 1
0 -> 0 (or -0, and similarly for the other test cases)
011 -> -2
1101 -> 2,1
1100 -> 2,0
11001 -> 2,-1
110001 -> 2,0,1
11100110001 -> 3,-2,0,1
00000001 -> 0,0,0,-1
01111011111111001111111111111110111111111111111100111111111111111111111110111111111111111111111111111111111111111111 -> -4,8,-15,16,-23,42
01111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 -> -127

2
Nitpick: เนื่องจากสิ่งนี้มี'0'sอยู่จึงไม่เป็นไปในทางเทคนิค ท้าทายดีแม้ว่า!
DJMcMayhem

4
@DJMcMayhem Nitpick ไปที่ nitpick: ในทางเทคนิคแล้วฉันไม่เคยบอกว่ามันเป็นเรื่องน่ากลัว มันเป็นส่วนเสริมของเอกภาพที่ฉันเรียกว่า ;)
DLosc

@DJMcMayhem IMO ความท้าทายนั้นมีเฉพาะที่ตัวคั่น ( 0) และคำนำหน้าเครื่องหมายลบ ( 0) เหมือนกันแม้ว่าจะยังไม่ชัดเจนเนื่องจากคุณไม่สามารถมีเครื่องหมายลบในระหว่างตัวเลข (เป็น182--693-1ตัวเลขหรือไม่ไม่ได้ และไม่ใช่1111011000101111เหตุผลเดียวกันทั้งหมด)
Erik the Outgolfer

ไม่เป็นไรถ้ารายการเอาท์พุทอยู่ในลำดับย้อนกลับของอินพุต?
DJMcMayhem

ทศนิยมทางเทคนิคไม่ใช่ทศนิยมเพราะมันใช้สัญลักษณ์ '-'
Unlambder

คำตอบ:


10

Python 2 , 73 70 ไบต์

ฟังก์ชันที่รับสตริงเป็นอินพุตและส่งคืนการแทนค่าสตริงของรายการ Python ศูนย์สามารถแสดงทั้งโดย0และ-0(เมื่อมาถึงล่าสุด):

lambda s:`map(len,s.split('0'))`.replace('0, ','-').replace('--','0,')

คำอธิบาย

  1. splitสตริงอินพุตsบนศูนย์
  2. ใช้ความยาวของแต่ละสตริงในรายการผลลัพธ์ (โดยใช้map)

นั่นทำให้เราอยู่ไกล เลขศูนย์เป็นตัวคั่นหลังจากทั้งหมด และตัวเลขนั้นไม่เหมือนกันดังนั้นจึงlenแปลงเป็นทศนิยมได้อย่างสะดวก แต่ตอนนี้เราได้ messed up 0ทั้งหมดที่ใช้งานที่ไม่ใช่ของตัวคั่น โชคดีที่การใช้ตัวคั่นที่ไม่ใช่ทั้งหมดเป็นศูนย์นำหน้าดังนั้นพวกเขาจึงมาหลังจากตัวคั่นศูนย์และให้สตริงที่มีความยาวเป็นศูนย์ ( '00'.split('0') == ['', '', '']) ผู้สตริงความยาวเป็นศูนย์แล้วก็กลายเป็นเพราะ0len

  1. เปลี่ยนรายการเป็นสตริง ( โดยใช้ "อัญประกาศย้อนกลับ" ) เพื่อให้เราสามารถแก้ไขปัญหาได้ง่ายขึ้น
  2. replaceแต่ละศูนย์ที่นำหน้าหมายเลขอื่นโดยใช้เครื่องหมายลบบนหมายเลขนั้นแทน ที่แก้ไขการใช้0เป็นสัญญาณ แต่จะแบ่งศูนย์ตัวอักษร ศูนย์ตัวอักษรถูกนำหน้าด้วยตัวคั่นดังนั้นตอนนี้พวกเขากลายเป็นเครื่องหมายขีดคั่นคู่ในหมายเลขถัดไป
  3. replaceแต่ละ--หลังเป็น0องค์ประกอบใน "รายการ"

1
ยินดีต้อนรับสู่ PPCG!
Steadybox

นี่เป็นวิธีที่สร้างสรรค์จริงๆ! คุณอาจต้องการเพิ่มคำอธิบายสั้น ๆ เพื่อให้คนที่ไม่พูดภาษา Python สามารถชื่นชมคำตอบของคุณได้เช่นกัน
DLosc

@DLosc ขอบคุณฉันไม่รู้เกี่ยวกับ backtick คำอธิบายที่ฟุ่มเฟือยยังเพิ่ม
Mercator

8

เรติน่า23 23ไบต์

(.)0
$1 
01
-1
1+
$.&

ลองออนไลน์!

ขั้นตอนแรก(.)0<newline>$1<space>ตรงกับตัวอักษรใด ๆ 0ตามมาด้วย การแข่งขันจะถูกแทนที่ด้วยอักขระตัวแรกตามด้วยช่องว่าง สิ่งนี้จะแยกสตริงในแต่ละหมายเลข

ขั้นตอนที่สอง01<newline>-1แทนที่0'ก่อนบล็อกของ1' S เพื่อที่จะ-เข้าสู่ระบบ

ขั้นตอนสุดท้าย1+<newline>$.&ตรงกับบล็อคทั้งหมดของ1และแทนที่ด้วยความยาวของกลุ่ม

นี่คือตัวอย่างที่มีเอาต์พุตของแต่ละด่าน


ดีมาก - ทั้งหมดของความคิดของฉันดูเหมือนนาฬิกาในวันที่ 24 ไบต์ ...
นีล

1
คุณช่วยเพิ่มคำอธิบายได้ไหม? ฉันไม่พูดเรตินา
Daniel

@Dopapp เพิ่มคำอธิบาย
OVS

7

เป็นกลุ่ม 56 ไบต์

:s/\v(0?1*)0?/\1\r/g|%s/0/-/|%s/1*$/\=len(submatch(0))
D

ลองออนไลน์!

ฉันยังไม่ได้โพสต์เป็นกลุ่มในขณะที่ ฉันมักจะใช้เสียงเรียกเข้าเพราะ V เป็นบางครั้งอาการปวด เพราะcountคำสั่งที่สมบูรณ์แบบสำหรับการรับจำนวน '1' บนบรรทัดจะเขียนทับ '0 ใด ๆ ในบรรทัดดังนั้นเราจึงไม่สามารถปฏิเสธได้ในภายหลัง

คำอธิบาย:

นี่คือหนึ่งไบต์ที่สั้นกว่าจากนั้นตรงไปตรงมา:

:s/\v(0?1*)0?/\1\r/g
:%s/0/-
:%s/1*$/\=len(submatch(0))
D

เนื่องจากการผูกมัดคำสั่ง ตั้งแต่นั้นแยกคำสั่งฉันจะใช้มันสำหรับคำอธิบาย

:s/                     " Substitute
                        " Search for...
   \v                   "   Enable 'magic'. This determines whether certain atoms require a backslash or not.
                        "   Without it we would have: '\(0\?1*\)0\?', which is 2 bytes longer
      0?                "   An optional 0
        1*              "   Followed by any number of '1's
     (    )             "   (call that group 1)
           0?           "   Followed by another optional 0
             /          " Replace it with...
              \1        "   Subgroup 1
                \r      "   A newline
                  /g    " Do this for every match on the current line.

ตอนนี้หมายเลขยูนารีที่ลงนามแต่ละหมายเลขนั้นอยู่ในแต่ละบรรทัด ใช้ '11100110001' เป็นตัวอย่าง ณ จุดนี้เราจะได้:

111
011
0
1

:%s/0   " Replace every 0
     /- " With a dash  

:%s/1*$/                    " Replace every run of 1's at the end of a line
        \=len(submatch(0))  " With the length of said run

เนื่องจากเราเพิ่มบรรทัดใหม่ในตอนท้ายของการแข่งขันแต่ละครั้งเราจึงมีบรรทัดว่างก่อนดำเนินการ หลังจากใช้งานแล้วเราจะมี '0' (เพราะตรงกับจำนวน 0 '1) ดังนั้นเราแค่เรียกDลบบรรทัดนี้ทิ้งไว้ให้ว่าง


ฮึ. :%s/1+$/จะทำให้คุณสั้นลงหนึ่งไบต์ถ้าไม่ต้องการแบ็กสแลช+:(
NieDzejkob

@NieDzejkob ฉันไม่เข้าใจว่าทำไมจะสั้นกว่านี้ และนั่นจะให้-แทน0หรือ-0
DJMcMayhem

ฉันต้องการกำจัดบรรทัดสุดท้ายด้วยวิธีนี้: P ไม่เป็นไร
NieDzejkob

7

Haskell , 68 66 ไบต์

f(x:r)|(a,b)<-span(>0)r=([(0-),(1+)]!!x$sum a):[z|_:t<-[b],z<-f t]

ลองออนไลน์! รับอินพุตเป็นรายการของศูนย์และรายการ ตัวอย่างการใช้งาน: อัตราผลตอบแทนf [0,0,0,1,1][0,-2]

คำอธิบาย:

การจับคู่รูปแบบในการf(x:r)|(a,b)<-span(>0)rผูกxกับองค์ประกอบแรกของการป้อนข้อมูลaไปยังรายการ (อาจว่างเปล่า) ของต่อไปนี้1และbส่วนที่เหลือของการป้อนข้อมูล ได้รับการป้อนข้อมูล[0,1,1,1,0,0,1]ที่เราได้รับx=0, และa=[1,1,1]b=[0,0,1]

จำนวนปัจจุบันแล้วทั้งผลรวมของaเมื่อตะกี้ถ้าx=0หรือผลรวมของบวกหนึ่งถ้าa x=1นี้จะทำได้โดยการจัดทำดัชนีที่มีxลงในรายการที่มีการปฏิเสธและเพิ่มฟังก์ชั่นและการใช้ฟังก์ชั่นที่จะส่งผลให้ผลรวมของ:a[(0-),(1+)]!!x$sum a

รายการส่วนที่เหลือbว่างเปล่าหรือมีศูนย์คั่นและหมายเลขถัดไป รายการเข้าใจ[z|_:t<-[b],z<-f t]พยายามที่จะตรงกับbในรูปแบบที่เป็นองค์ประกอบลืมหัวและผูกส่วนที่เหลือของรายการไป_:t tหากbว่างเปล่าการแข่งขันนี้จะล้มเหลวและความเข้าใจในรายการจะประเมิน[]ซึ่งเป็นกรณีพื้นฐานสำหรับการสอบถามซ้ำ มิฉะนั้นฟังก์ชั่นfที่นำมาใช้ซ้ำไปtและรายการประเมินความเข้าใจกับองค์ประกอบทั้งหมดจากผลของzf t


3

ภาษา Wolfram (Mathematica) , 80 ไบต์

StringCases[#<>"0",x_~~Shortest@y___~~"0":>(If[x=="0",-#,#+1]&)@StringLength@y]&

ลองออนไลน์!

ใช้งานเครื่องจักรในทางที่ผิดStringCasesเนื่องจากไม่ได้ตรวจสอบรูปแบบที่ทับซ้อนกัน เนื่องจากเราค้นหาจากซ้ายไปขวาโดยไม่ทับซ้อนกันเราจึงได้จำนวนเต็มที่เราต้องการเท่านั้น

คำอธิบาย

#<>"0"

ผนวกศูนย์ในตอนท้าย

StringCases

ค้นหารูปแบบต่อไปนี้ทั้งหมด ...

x_~~Shortest@y___~~"0"

อักขระตัวเดียว (เรียกว่าx) ตามด้วยสตริงที่มีความยาวเป็นศูนย์สั้นที่สุดหรือยาวกว่านั้น (เรียกว่าy) ตามด้วยศูนย์

(If[x=="0",-#,#+1]&)@StringLength@y

นำไปใช้กับรูปแบบการจับคู่: yใช้ความยาวของ หากxเป็นศูนย์ให้ลบล้างค่า อื่นเพิ่มขึ้นหนึ่ง

สิ่งนี้ครอบคลุม00เช่นกันเนื่องจากyจะเป็นสตริงว่างและเราจะคำนวณ-0( == 0)


3

Brain-Flak , 94 (70?) ไบต์

([]){{}({(<()>)()}{}(<>)<>{<([{}]<>{})><>})
{{}<>([{}])(<>)}{}{}([])}{}<>([]){{}({}<>)<>([])}<>

ลองออนไลน์!

นี่เป็นเรื่องย่อที่ทำให้สมองแตก

นี่เป็นเวอร์ชันที่มีความคิดเห็น / อ่านได้:

([])

{

    #Pop the Stack height
    {}

    (
        #If there isn't a leading 0, evaluate to 1...
        {
            (<()>)

            ()
        }

        #Pop the 0
        {}

        #Push a 0 onto the alternate stack
        (<>)
        <>

        #Run of '1's
        {
            #Decrement the alternate stack
            <([{}]<>{})>
            <>
        }

        #And push it here
    )

    #Was there a not leading 0?

    {
        {}

        #Invert the value on the alternate stack
        <>([{}])(<>)
    }

    #Pop 2 zeros
    {}{}


    ([])

}{}<>

#Push stack height
([])

#Reverse the stack
{

    {}

    ({}<>)

    <>([])

}<>

หากผลลัพธ์สามารถย้อนกลับได้เราสามารถทำเช่นนี้แทน 70

([]){{}({(<()>)()}{}(<>)<>{<([{}]<>{})><>}){{}<>([{}])(<>)}{}{}([])}<>

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

([]){{}({(<()>)()}{}(<>)<>{<([{}]<>{})><>})
{{}<>([{}])(<>)}{}{}(<>())<>([])}{}<>{{}({}<>)<>}<>

ซึ่งก็คือ 94 ไบต์



3

Husk , 20 18 17 15 14 ไบต์

Γ~:?Σṁ_Πȯ₀tΣġ/

ลองออนไลน์!

คำอธิบาย

Γ~:?Σṁ_Πȯ₀tΣġ/  Input is a list, say x = [0,1,1,0,0,0,1,1]
            ġ   Group by
             /  division.
                This splits x right before each 0: [[0,1,1],[0],[0],[0,1,1]]
Γ               Deconstruct into head y = [0,1,1] and tail z = [[0],[0],[0,1,1]]
   ?Σṁ_Π        Apply to y:
       Π         Product: 0
   ?Σ            If that is nonzero, take sum of y,
     ṁ_          else take sum of negated elements of y: u = -2
        ȯ₀tΣ    Apply to z:
           Σ     Concatenate: [0,0,0,1,1]
          t      Drop first element: [0,0,1,1]
         ₀       Recurse: [0,2]
 ~:             Tack u to the front: [-2,0,2]

การแยกออกเป็นแบบนี้ ġ/แยกการโต้เถียงระหว่างองค์ประกอบแต่ละคู่a,bซึ่ง/a bเป็นเท็จ /a bเป็นส่วนที่มีการขัดแย้งพลิกดังนั้นหารด้วยb aค่าที่เกี่ยวข้องในโปรแกรมนี้คือ:

  • /1 1ให้1(ความจริง)
  • /1 0ให้0(เท็จ)
  • /0 1ให้Inf(บวกอนันต์บวกความจริง)
  • /0 0ให้Any(ค่าเหมือน NaN พิเศษเท็จ)

3

Acc !! , 252 237 ไบต์

N
Count i while _/48 {
Count n while 48/_ {
Write 45
50+N
}
_+49/_*50
Count u while _%50/49 {
_+100-_%50+N
}
_/50-1
Count h while _/200 {
Write _/200+48
_%200+1
}
Count t while _/20+_%2 {
Write _/20+48
_%20-_%2
}
Write _/2+48
Write 9
N
}

-0การใช้ประโยชน์ ส่งออกตัวเลขคั่นด้วยอักขระแท็บโดยมีแท็บต่อท้ายลองออนไลน์!

จำนวนเวลาที่เขียนอัลกอริทึมจริง: 20 นาที ระยะเวลาในการดีบักรหัสผลลัพธ์ทศนิยมของฉัน: 45 นาที : ^ P

ด้วยความเห็น

ฉันไม่รู้ว่าความคิดเห็นเหล่านี้อธิบายรหัสได้ดีมาก - พวกเขาอ้างอิงจากบันทึกของฉันกับตัวเองในขณะที่ฉันเขียนมันดังนั้นพวกเขาจึงเข้าใจว่าACC เป็นอย่างไรบ้าง!! โรงงาน หากมีสิ่งใดต้องการคำอธิบายเพิ่มเติมแจ้งให้เราทราบและฉันจะพยายามทำให้ชัดเจนยิ่งขึ้น

# We partition the accumulator _ as [number][flag][nextchar]
# [flag] is a 2-value slot and [nextchar] a 50-value slot
# So [nextchar] is _%50, [flag] is _/50%2, [number] is _/100
# [flag] is 1 if we're in the middle of reading a number, 0 if we're between numbers
# It is also used for outputting as decimal (see below)
# Possible input characters are 0, 1, and newline, so [nextchar] is 48, 49, or 10

# Read the first character
N
# Loop while the character we just read is 0 or 1 and not newline
Count i while _/48 {
  # What we do in the loop depends on the combination of [flag] and [nextchar]:
  # 0,48 (start of number, read 0) => write minus sign, [flag] = 1, read another char
  # _,49 (read 1) => increment [number], [flag] = 1, read another char
  # 1,48 (middle of number, read 0) => write/clear [number], status = 0, read another
  #      char
  # 1,10 (middle of number, read <cr>) => ditto; the next read will be 0 for eof, which
  #      means the acc will be less than 48 and exit the loop

  # Process leading 0, if any
  Count n while 48/_ {
    # acc is 48: i.e. [number] is 0, [flag] is 0, [nextchar] is 48 (representing a 0)
    # Output minus sign
    Write 45
    # Set [flag] to 1 (thereby exiting loop) and read [nextchar]
    50+N
  }
  # If number starts with 1, then we didn't do the previous loop and [flag] is not set
  # In this case, acc is 49, so we add (50 if acc <= 49) to set [flag]
  _+49/_*50

  # Process a run of 1's
  Count u while _%50/49 {
    # [nextchar] is 49 (representing a 1)
    # Increment [number] and read another
    _+100-_%50+N
  }

  # At this stage, we know that we're at the end of a number, so write it as decimal
  # This is "easier" (ha) because the number has at most three digits
  # We shift our partitioning to [number][flag] and set [flag] to 0
  _/50-1

  # Output hundreds digit if nonzero
  # Since [number] is _/2, the hundreds digit is _/200
  Count h while _/200 {
    Write _/200+48
    # Mod 200 leaves only tens and units; also, set [flag] to 1
    _%200+1
  }
  # Output tens digit (_/20) if nonzero OR if there was a hundreds digit
  # In the latter case, [flag] is 1
  Count t while _/20+_%2 {
    Write _/20+48
    # Mod 20 leaves only units; clear [flag] if it was set
    _%20-_%2
  }
  # Write units unconditionally
  Write _/2+48

  # Write a tab for the separator
  Write 9
  # Read another character
  N
}


2

R , 119 ไบต์

function(x){n=nchar
y=regmatches(x,regexec("(0?)(1*)0?([01]*)",x))[[1]]
cat((-1)^n(y[2])*n(y[3]),"")
if(y[4]>0)f(y[4])}

ลองออนไลน์!

รหัสใช้โซลูชันนี้จาก stackoverflowสำหรับปัญหาที่เกี่ยวข้อง (ขอบคุณ jeales สำหรับแนวคิด) เอาต์พุตเป็นสตริงที่คั่นด้วยช่องว่างพิมพ์เป็น stdout


2

เยลลี่ ,  19  18 ไบต์

จะต้องมีวิธีที่ดีกว่า ...

®ḢN$Ḣ©?ṄEȧ
ṣ0L€ÇL¿

โปรแกรมเต็มรูปแบบพิมพ์แต่ละหมายเลขตามด้วย linefeed

ลองออนไลน์!

อย่างไร?

®ḢN$Ḣ©?ṄEȧ - Link 1, print first number and yield next input: list of numbers, X
           -                              e.g. [8,0,15,16,...] or [0,4,8,0,15,16,...]
      ?    - if...
    Ḣ      - condition: yield head and modify  8([0,15,16,...])   0([4,8,0,15,16,...])  
     ©     -            (copy to register)     8                  0
®          - then: recall from the register    8
   $       - else: last two links as a monad:
 Ḣ         -         yield head and modify                        4([8,0,15,16,...])
  N                  negate                                      -4
       Ṅ   - print that and yield it           8                 -4
        E  - all equal (to get 0 to be truthy) 1                  1
         ȧ - AND the (modified) input          [0,15,16,...]      [8,0,15,16,...]
           -   (ready to be the input for the next call to this link)

ṣ0L€ÇL¿ - Main link: list e.g. [0,1,0,0,0,0,1,1]
ṣ0      - split at zeros       [[],[1],[],[],[],[1,1]
  L€    - length of €ach       [0,1,0,0,0,2]
      ¿ - while...
     L  - condition: length                           1  1  1  0  ([0,1,0,0,0,2], [0,0,0,2], [0,2], [])
    Ç   - action: call the last link (1) as a monad  -1  0 -2     ( - 1            - 0        - 2)

1

QBasic, 88 86 ไบต์

1u$=INPUT$(1)
z=u$<"1
IF n*z THEN?(1-2*s)*(n-s):s=0:n=0ELSE s=s-z:n=n+1
IF"!"<u$GOTO 1

มันสนุกมาก การแก้ไขหลายครั้งเริ่มต้นจากรุ่น 107 ไบต์ทำให้หนึ่งใน QBasic บิตที่สับสนที่สุดฉันคิดว่าฉันเคยเขียน (แก้ไข: ผิดปกติพอฉันสามารถเล่นกอล์ฟ 2 ไบต์ด้วยการทำให้รหัสชัดเจนขึ้น)

หมายเหตุ: โปรแกรมนี้อ่านข้อมูลผู้ใช้ครั้งละหนึ่งตัวอักษรโดยไม่สะท้อนไปที่หน้าจอ (ผลของการใช้INPUT$(1)แทนINPUTคำสั่งปกติ) ดังนั้นเมื่อคุณพิมพ์คุณจะไม่เห็นตัวเลข 1 และ 0 แต่ตัวเลขทศนิยมจะปรากฏขึ้นเมื่อมีการคำนวณ ตรวจสอบให้แน่ใจว่าได้กดEnterที่ส่วนท้ายของอินพุตเพื่อดูหมายเลขสุดท้ายและจบโปรแกรม

เวอร์ชันที่ไม่ดี

sign = 0
num = 0
DO
  digit$ = INPUT$(1)
  isZero = (digit$ < "1")
  IF num > 0 AND isZero THEN
    PRINT (1 - 2 * sign) * (num - sign)
    sign = 0
    num = 0
  ELSE
    IF isZero THEN sign = 1
    num = num + 1
  END IF
LOOP WHILE "!" < digit$

คำอธิบาย

(AKA "อะไรนะที่ยังไม่สมเหตุสมผล!")

กลยุทธ์พื้นฐานคือการวนรอบที่คว้าตัวละครตัวหนึ่งจากINPUT$(1)แต่ละครั้งผ่านไปทำสิ่งที่มันและวนซ้ำตราบใดที่ตัวละครมีค่า ASCII มากกว่าที่! (เช่นไม่ได้ขึ้นบรรทัดใหม่)

เราติดตามความคืบหน้าของตัวเลขโดยใช้ตัวแปรสองตัว numคือจำนวนอักขระในหมายเลขยูนารีที่ลงนามปัจจุบัน (รวมถึงศูนย์นำหน้า) signคือ1ถ้าจำนวนมีศูนย์นำ0ถ้าไม่ ทั้งสองอย่างนี้จำเป็นต้องเริ่มต้นใช้งาน0ซึ่งดีมากสำหรับรุ่น golfed เนื่องจากตัวแปรตัวเลขใน QBasic จะเริ่มต้นโดยอัตโนมัติเพื่อ0จะเริ่มต้นโดยอัตโนมัติ

เมื่อใดก็ตามที่เราอ่านตัวอักษรเป็นสิ่งแรกคือการกำหนดว่าจะเป็นหรือ1 เราจะใช้ผลนี้เป็นครั้งที่สองเพื่อให้เราเก็บไว้ใน0 isZeroในทางเทคนิคชื่อนั้นทำให้เข้าใจผิดเนื่องจากค่าจะเป็นจริงถ้าตัวละครเป็นบรรทัดใหม่ โปรดทราบว่าความจริงใน QBasic คือ-1และเท็จคือ0คือ

ตอนนี้ถ้าเราอยู่ระหว่างการอ่านตัวเลข ( num > 0) และเราไปถึงศูนย์หรือจุดสิ้นสุดของการป้อนข้อมูล ( isZero) เราต้องคำนวณตัวเลขที่เราอ่านเสร็จแล้ว

  • signร้านค้า0สำหรับบวก1สำหรับเชิงลบ ที่จะได้รับ1สำหรับในเชิงบวกและเชิงลบเราต้อง-11-2*sign
  • numเก็บขนาดที่ถูกต้องสำหรับผลบวก แต่มากกว่าขนาดหนึ่งสำหรับค่าลบ (เนื่องจากมีเครื่องหมายเครื่องหมาย) ดังนั้นเราสามารถใช้num-signสำหรับขนาด

ทวีคูณเหล่านี้เข้าด้วยกันและพิมพ์; จากนั้นรีเซ็ตsignและเป็นnumเพื่อ0เตรียมการอ่านหมายเลขถัดไป

มิฉะนั้น (ถ้าเรายังไม่ถึงศูนย์หรือถ้าเราไปถึงศูนย์ที่จุดเริ่มต้นของตัวเลข) เราจะอัปเดตsignและnumดังนี้:

  • signกลายเป็น1ว่าเรากำลังมองหาที่ศูนย์นำ; ไม่อย่างนั้นถ้าเราดูที่มันก็จะอยู่ที่อะไรก็ตาม รหัส golfed คือs=s-zซึ่งมีจำนวนในสิ่งเดียวกัน:
    • ถ้าเป็นศูนย์ชั้นนำคือz -1เนื่องจากsมีการรับประกันว่าจะเป็น0(เพราะนี่คือจุดเริ่มต้นของหมายเลขใหม่) s-zจะเป็น1จะ
    • ถ้าเป็นอย่างใดอย่างหนึ่งคือz 0จากนั้นs-zยังคงอยู่ในสิ่งที่sมีคุณค่าก่อนหน้านี้
  • num เพิ่มขึ้น

แค่นั้นแหละ!


0

JavaScript (ES6), 60 ไบต์

ส่งคืนรายการจำนวนเต็มที่คั่นด้วยช่องว่าง

s=>(0+s).replace(/00?1*/g,s=>(l=s.length,+s[1]?l-1:2-l)+' ')

กรณีทดสอบ


0

ลัวะ 58 ไบต์

(...):gsub("(0?)(1*)0?",function(s,n)print(#n-2*#s*#n)end)

ลองออนไลน์!

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

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