ทำนายดินถล่ม


22

แผ่นดินถล่ม

ในการท้าทายนี้งานของคุณคือการคาดการณ์ขอบเขตของความเสียหายที่เกิดจากแผ่นดินถล่มขนาดใหญ่ เราใช้ต่อไปนี้ง่ายรูปแบบสองมิติมันแปรโดยความสูงเริ่มต้น h >= 0และค่าสัมประสิทธิ์ที่สำคัญ c > 0คุณเริ่มต้นด้วยหน้าผาสูงhและมีการสันนิษฐานว่าภูมิประเทศนั้นแบนราบไปทางซ้ายและทางขวาของมันอย่างไม่สิ้นสุด สำหรับh = 6สถานการณ์จะเป็นดังนี้:

##########
##########
##########
##########
##########
##########
-----------------------

-มีข้อเท็จจริงอสังหาริมทรัพย์และ#เป็นดินที่ไม่เสถียร หากความแตกต่างของความสูงระหว่างสองคอลัมน์ที่อยู่ใกล้เคียงเป็นมากกว่าcการถล่มเกิดขึ้น: ด้านบนcหน่วยของดินจากคอลัมน์ด้านซ้ายล้มลงไปยังcคอลัมน์ทางด้านขวาหนึ่งไปยังแต่ละ คอลัมน์ที่ไม่ว่างด้านขวาสุดในรูปนั้นไม่เสถียรc = 2ดังนั้นจึงมีการเรียกดินถล่ม:

#########
#########
##########
##########
##########
############
-----------------------

คอลัมน์ยังคงไม่เสถียรซึ่งทำให้เกิดแผ่นดินถล่มครั้งที่สอง:

#########
#########
#########
#########
############
############
-----------------------

ตอนนี้คอลัมน์ทางซ้ายไม่เสถียรดังนั้นดินถล่มใหม่จึงถูกเรียกขึ้นมาที่นั่น:

########
########
#########
###########
############
############
-----------------------

หลังจากนี้หน้าผาก็มั่นคงอีกครั้ง สิ่งที่ดีเกี่ยวกับโมเดลนี้คือลำดับของการถล่มที่ประมวลผลไม่สำคัญ: ผลลัพธ์ที่ได้จะเหมือนกัน

งาน

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

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

กรณีทดสอบ

h c -> outputเหล่านี้จะได้รับในรูปแบบ

0  2  -> 0
2  3  -> 0
6  2  -> 4
6  6  -> 0
10 1  -> 10
15 1  -> 14
15 2  -> 11
15 3  -> 6
40 5  -> 16
80 5  -> 28
80 10 -> 17

คำตอบ:


5

CJam, 62 57 ไบต์

เท่าที่ฉันเห็นนี่เป็นแนวทางที่แตกต่างอย่างสิ้นเชิงในการใช้งานโซลูชันจากคำตอบของ aditsu

q~:C;:HaH)*H){(:I\_@>2<:-C>{I0a*C~)+C1a*+]z1fb_,}I?}h-H-,

อินพุตจะอยู่ในรูปแบบของ h c

ตัวอย่าง:

80 5

เอาท์พุท:

28

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

ตรรกะตรงไปตรงมาที่นี่ด้วยเทคนิคเล็กน้อยที่ใช้ในการลดขนาดรหัส

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

การขยายรหัส

q~:C;:HaH)*H){(:I\_@>2<:-C>{I0a*C~)+C1a*+]z1fb_,}I?}h-H-,
q~:C;:HaH)*H)
q~:C;:H                  "Read the input, evaluate it, store height in H and coeff. in C";
       aH)*              "Wrap the height number in an array and repeat it H + 1 times";
           H)            "Put H+1 on stack, representing the current index of iteration";
{(:I\_@>2<:-C>{I0a*C~)+C1a*+]z1fb_,}I?}h
(:I\_@>2<:-C>
(:I                      "Decrement the current index and store it in I";
   \_                    "Swap to put array on top and make 1 copy";
     @>2<                "Get the two elements starting from Ith index";
         :-              "Get the difference. The best part of this approach is that";
                         "For the right most index, where there is only element, it";
                         "returns the element itself, which is the expected difference";
           C>            "Check if difference is greater than C";
{I0a*C~)+C1a*+]z1fb_,}   "This block will be executed when the difference is more than C";
 I0a*                    "Get an array of I length and all elements 0";
     C~)+                "Get -C value and append it to the above array";
         C1a*+           "Get C length array of 1s and concat with the above array";
              ]          "Wrap the two arrays, the cliff and the above one in an array";
               z1fb      "Transpose to get number pairs and add those pairs. For example";
                         "If we are at the right most index with H = 80 and C = 5,";
                         "The right section of the cliff looks like:";
                         "[ ... 80 80 80 80 80] and the array created in above step";
                         "looks like [ ... 0 0 0 0 -5 1 1 1 1 1]. After z, we have:";
                         "[ ... [80 0] [80 0] [80 0] [80 0] [80 -5] [1] [1] [1] [1] [1]]";
                         "After 1fb we get [ ... 80 80 80 80 75 1 1 1 1 1]";
                   _,    "Take a copy of the above resultant array and take its length";
I?                       "If difference was not greater than C, put I on stack";
                         "Now we either have the decremented index or new array length";
                         "on stack."
{ ... }h                 "This is a do while loop which makes sure that we iterate to";
                         "the left of the array. This loops runs till the top stack";
                         "element is 0 while not popping the top element";
        -H-,             "After the loop, we have the final cliff array and 0 on stack";
                         "Remove any 0 elements from the array, then remove any H";
                         "elements from the array and then take length to get the";
                         "number of columns which were modified";

ลองออนไลน์ได้ที่นี่


แพ้รู้อีก: p ทำได้ดีมาก :)
aditsu


นี่ไม่ใช่ครั้งแรกที่มีคนตีฉันที่ CJam และไม่ใช่ครั้งแรกที่คุณทำเช่นนั้นแม้ว่าจะไม่แน่ใจว่าคุณเคยแข่งขันโดยตรงมาก่อนหรือไม่
aditsu

Heh :) ทุกอย่างเกี่ยวกับอัลกอริทึม :)
เครื่องมือเพิ่มประสิทธิภาพ

4

CJam - 70

q~:C;:H0]H*$W%{[__W<\1>]z{~-}%{C>}#):I{I(_2$=C-tC,{I+_2$=)t}/}0?}h-H-,

ลองที่http://cjam.aditsu.net/

คำอธิบาย:

q~                    read and evaluate the input
:C;                   store the 2nd number in C and remove
:H                    store the first number in H
0]H*                  make an array [H 0] and repeat it H times
$W%                   sort and reverse, obtaining [(H H's) (H 0's)] (initial cliff)
{                     loop...
    [__W<\1>]         make an array with the cliff without the first column
                      and the cliff without the last column
    z{~-}%            subtract the 2 arrays to get the height differences
    {C>}#             find the index of the first height diff. greater than C
    ):I               increment and store in I
    {                 if the value is non-zero (i.e. landslide occurring)
        I(_2$=C-t     subtract C from the corresponding column height
        C,            make an array [0 1 ... C-1]
        {             for each of those numbers
            I+        add I, obtaining a column index where some soil falls
            _2$=)t    increment the column height
        }/            end loop
    }0?               else break outer loop; end if
}h                    ...while the condition is true
-H-                   remove all 0 and H from the final stable cliff
,                     count the remaining columns

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


4

Python, 200 190 174

h,c=input();q=[h]*h+[0]*h
try:
 while 1:
    d=[b-a for a,b in zip(q[1:],q)];g=max(d);a=d.index(g)
    for i in range(c):q[a+1+i]+=1/(g>c);q[a]-=1
except:print sum(h>i>0for i in q)

รุ่นขยาย:

h, c = input()
# Initialize the heights
q = [h]*h + [0]*h
try:
    while 1:
        # Difference between the heights
        d = [b-a for a,b in zip(q[1:],q)]
        # It may error here, when h == 0, but thats okay
        g = max(d)
        a = d.index(g)
        for i in range(c):
            # This is the termination condition, when g <= c
            q[a+1+i] += 1 / (g>c)
            # Save the newline; also move this line to after termination
            q[a] -= 1
except:
    # Count all heights that have changed
    print sum(h > i > 0 for i in q)

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


ดี! คุณสามารถวางวงเล็บสี่เหลี่ยมจัตุรัสไว้ภายในsum2 ไบต์ นอกจากนี้โดยปกติแล้วจะเป็นการดีกว่าที่จะกำหนดโปรแกรมเต็มรูปแบบใน Python รับอินพุตh,c=input()และพิมพ์ผลลัพธ์ในท้ายที่สุด
Zgarb

ฉันไม่ได้สังเกตเห็นวิธีแก้ปัญหานี้และโพสต์ของฉันแย่ลงเล็กน้อยหนึ่ง D: โอ้ดีการแข่งขันเป็นสิ่งที่ดี บางทีฉันจะดูว่าฉันสามารถโกนไบต์จากฉันได้ไหม โดยวิธีการที่พลิกรถของคุณได้ในของคุณสามารถช่วยให้คุณประหยัดที่หนึ่ง:sum sum(h>i>0for i in q)
undergroundmonorail

@undergroundmonorail ฉันพยายามอย่างหนัก แต่ฉันกลัววิธีการของคุณจะดีกว่าเพียงแค่ :(. c=0ช่วยประหยัดไบต์ (ผมไม่สามารถแสดงความคิดเห็นในคำตอบของคุณ).
ฟิลิปป์

4

Python 2 - 194 158 ไบต์

h,c=input()
b=l=[h]*h+[0]*h
while b:
 b=0
 for i in range(len(l)-1):
  if l[i]-l[i+1]>c:
    for j in range(c):l[i-~j]+=1
    l[i]-=c;b=1
print sum(h>e>0for e in l)

(โปรดทราบว่าตัวแปล markdown SE ของ SE จะแปลงแท็บตัวอักษรเป็นช่องว่าง 4 บรรทัดบรรทัดที่ 7 และ 8 ของโปรแกรมนี้มีเพียงแท็บเดียว [เช่นหนึ่งไบต์] ของการเยื้องแต่ละครั้ง)

ใช้อินพุตบน stdin hก่อน ตัวอย่างเช่น:

$ ./landslide.py <<< '6, 2'
4

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

คำอธิบาย

ก่อนอื่นhและcอ่านจาก stdin ใน Python 2 input()มีค่าเท่ากับeval(raw_input())ซึ่งเป็นเหตุผลที่ฉันขอจุลภาคคั่นตัวเลข input()ให้ผลตอบแทน tuple ของ ints ไม่จำเป็นต้องมีการแปลง

ถัดไปจะทำการสร้างรายการจำนวนเต็ม มัน2*hยาว ครึ่งแรกเป็นhครึ่งหลังคือ 0 ฉันไม่มีเหตุผลที่จะแสดงว่ามันเพียงพอที่จะจำลองhs ไม่มีที่สิ้นสุดไปทางซ้ายและ 0s ไปทางขวา ฉันเพิ่งสะดุดมันและมันใช้งานได้กับทุกกรณีทดสอบดังนั้นหากใครบางคนสามารถค้นหาอินพุตมันไม่ได้ผลสำหรับฉันจะเปลี่ยนมันด้วยความยินดี อย่างไรก็ตามรายการนี้จะเรียกว่าแต่สำเนาของมันอีกที่เรียกว่าlb

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

ส่วนที่เหลือของลูปคือการจำลองที่เกิดขึ้นจริง มันไร้เดียงสามากเป็นเพียงการแปลรหัสของคำอธิบายปัญหา หากองค์ประกอบใด ๆ ของlมีcค่ามากกว่ามากกว่าที่ติดตามมันจะถูกลบออกcและcองค์ประกอบต่อไปจะเพิ่ม 1 รายการลงไป (เวทมนตร์ระดับบิตที่ใช้ที่นี่เป็นเพียงวิธีการเขียนที่สั้นกว่าi+1+j) ในขณะที่ทำการแปลงเหล่านี้bถูกตั้งค่าเป็น 1 ครั้งแรกที่ไม่มีการแปลงเกิดขึ้นbจะอยู่ที่ 0 และการวนซ้ำจะสิ้นสุดลง

ใด ๆ ที่ประเมินการแสดงออกจริงกับTrueและเมื่อคุณพยายามที่จะทำคณิตศาสตร์ในการTrueประเมินถึง 1 เดียวกันเป็นจริงของFalseและ 0 บรรทัดสุดท้ายของโปรแกรมที่ใช้ในทุกองค์ประกอบของการlเป็นeในการแสดงออกh>e>0และผลบวกผล นี่จะได้รับจำนวนคอลัมน์มากกว่า 0 แต่ต่ำกว่าความสูงของหน้าผาดั้งเดิมซึ่งเป็นค่าที่คำถามถาม มันถูกพิมพ์และออกจากโปรแกรม


2
ไม่c-=cเทียบเท่ากับc=0?
Zgarb

...ว้าว. ขอบคุณที่เฝ้ามองฉันฉันควรจะจับได้ฮ่าฮ่า
undergroundmonorail

1
i+1+jสามารถเขียนได้เป็นi-~j
Sp3000

@ Sp3000 ฉันลืมเวทมนตร์เกี่ยวกับ bitwise โดยสิ้นเชิง! ขอบคุณ: D
undergroundmonorail

3

Haskell, 163 156 151 Bytes

h#c=sum[1|e<-(until=<<((==)=<<))s$r h++r 0,e`mod`h/=0]where r=replicate$h+1;s w@(x:y:z)|x==0=w|x>c+y=x-c:map(+1)(take c(y:z))++drop c(y:z)|1<2=x:s(y:z)

การใช้งาน: h#c, เช่น6#2เอาต์พุต4ใด

วิธีการทำงาน: ฟังก์ชั่นผู้ช่วยsทำแผ่นดินถล่มเดี่ยว ใช้ซ้ำ ๆsจนกระทั่งเอาท์พุทไม่เปลี่ยนแปลงอีกต่อไป นับองค์ประกอบที่ได้รับผลกระทบ

พบ "สมัครจนถึงการส่งออกไม่เปลี่ยนแปลง" ฟังก์ชั่น (คือuntil=<<((==)=<<)) ที่Stackoverflow


คุณสามารถบันทึกสองสามไบต์โดยกำหนดfเป็น infix ( h#c=...) และย้ายส่วนwhereคำสั่งไปยังบรรทัดเดียวกัน นอกจากนี้ยังมีวงเล็บบางที่จะหลั่งใช้$แม้ว่าฉันไม่แน่ใจว่ากี่ ...
Zgarb

@Zgarb: ขอบคุณสำหรับคำแนะนำ การแทนที่()ด้วย$is trail และ error สำหรับฉัน
nimi

3

Mathematica, 108 104 100 97 95

f=Max@#-Min@#&[0Range@#2//.{x___,k:##..&[a_,{#}],a_,y___}:>Sort@{x,##&@@({k}-1),a+#,y}/.{}->0]&

การใช้งาน:

f[c, h]

ตัวอย่าง:

f[5, 80]

28


2

C # 303 295

มันได้ผล!

แต่มันเป็น ....

int q(int n,int c){var s=Enumerable.Repeat(n,n).ToList();s.Add(0);var d=new HashSet<int>();var g=true;while(g){g=false;for(int i=s.Count-1;i>0;i--){int z=i;int y=i-1;if((s[y]-s[z])>c){s[y]-=c;d.Add(y);g=true;for(int j=1;j<=c;j++){s[y+j]++;d.Add(y+j);if(s[s.Count-1]>0)s.Add(0);}break;}}}return d.Count;}

ฉันต้องค้นหาภาษาใหม่;)

ฉันจะตรวจสอบสิ่ง CJam นี้ ...

ปรับปรุง:

int q(int n,int c){var s=Enumerable.Repeat(n,n).ToList();s.Add(0);var d=new HashSet<int>();var g=1>0;while(g){g=1<0;for(int i=s.Count-1;i>0;i--){int z=i,y=i-1;if((s[y]-s[z])>c){s[y]-=c;d.Add(y);g=1>0;for(int j=1;j<=c;j++){s[y+j]++;d.Add(y+j);if(s[s.Count-1]>0)s.Add(0);}break;}}}return d.Count;}

1
คุณยังสามารถเพิ่มประสิทธิภาพได้เล็กน้อย อาจจะเป็นint z=i;int y=i-1; ลูปจะไม่ทำสิ่งที่ซับซ้อนกับดัชนีของพวกเขาดังนั้นเช่นอาจจะint z=i,y=i-1;forfor(int i=s.Count-1;i>0;i--)for(int i=s.Count;--i>0;)1<0falseเป็นวิธีที่สั้นของการเขียน ฉันสงสัยว่าif(s[s.Count-1]>0)s.Add(0);อาจสูญเสียสภาพโดยไม่กระทบต่อความถูกต้องเพียงความเร็ว
Peter Taylor

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