Dự đoán sạt lở


22

Sạt lở

Trong thử thách này, công việc của bạn là dự đoán mức độ thiệt hại do một trận lở đất lớn. Chúng tôi sử dụng mô hình hai chiều được đơn giản hóa sau đây cho nó, được tham số hóa bằng chiều cao ban đầu h >= 0hệ số tới hạn c > 0 . Bạn bắt đầu với một vách đá có chiều cao hvà người ta cho rằng địa hình hoàn toàn bằng phẳng ở bên trái và bên phải của nó. Đối với h = 6, tình hình như thế này:

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

Đất -nền là bất động, và #đất không ổn định. Nếu chênh lệch độ cao giữa hai cột lân cận lớn hơn c, một vụ lở đất xảy ra: các cđơn vị đất trên cùng từ cột bên trái rơi xuống các ccột tiếp theo bên phải, mỗi cột một bên. Cột không trống bên phải trong hình không ổn định c = 2, do đó, một điểm lở được kích hoạt:

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

Cột vẫn không ổn định, gây ra sạt lở thứ hai:

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

Bây giờ, cột bên trái của nó đã trở nên không ổn định, do đó một vụ lở đất mới được kích hoạt ở đó:

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

Sau này, vách đá ổn định trở lại. Điều hay ho của mô hình này là thứ tự xử lý lở đất không thành vấn đề: kết quả cuối cùng là như nhau.

Nhiệm vụ

Chương trình của bạn được cung cấp các tham số nguyên hclàm đầu vào (thứ tự không quan trọng, nhưng bạn phải chỉ định nó trong câu trả lời của mình) và nó sẽ xuất ra tổng số cột mà lở đất ảnh hưởng. Điều này có nghĩa là số lượng cột trong vách đá ổn định có chiều cao nằm giữa 0h. Trong ví dụ trên, đầu ra đúng là 4.

Bạn có thể viết một chương trình đầy đủ hoặc một chức năng. Số byte thấp nhất sẽ thắng và các sơ hở tiêu chuẩn không được phép.

Các trường hợp thử nghiệm

Chúng được đưa ra trong định dạng 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

Câu trả lời:


5

CJam, 62 57 byte

Theo như tôi có thể thấy, đây là cách tiếp cận hoàn toàn khác để thực hiện giải pháp từ câu trả lời của aditsu.

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

Đầu vào đi theo hình thức h c

Thí dụ:

80 5

Đầu ra:

28

Làm thế nào nó hoạt động

Logic khá đơn giản ở đây với một vài thủ thuật được sử dụng để giảm kích thước mã.

  • Lấy mảng chiều dài h + 1( + 1cho h = 0trường hợp) với mỗi phần tử là hđại diện cho vách đá
  • Bắt đầu lặp từ chỉ số đúng nhất của mảng này
    • Nếu hai yếu tố từ chỉ số hiện tại có nhiều hơn c
      • Xóa ckhỏi phần tử chỉ mục hiện tại
      • Thêm 1vào ccác phần tử tiếp theo của mảng từ chỉ mục hiện tại
      • Làm cho chỉ mục hiện tại bằng với độ dài của mảng mới này
      • Điều này đảm bảo rằng chúng tôi ổn định các viên đá ở bên phải của chỉ số hiện tại trước
    • khác, giảm chỉ số hiện tại
  • Khi chúng tôi đạt được hầu hết các chỉ mục bên trái, chúng tôi đảm bảo rằng tất cả các chỉ mục liền kề có ít hơn hoặc bằng cchênh lệch
  • Loại bỏ bất kỳ 0hoặc hgiá trị từ mảng và nhận được chiều dài.

Mở rộng mã

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";

Dùng thử trực tuyến tại đây


Làm lại một lần nữa: p Làm tốt lắm :)
aditsu

@aditsu lại?
Trình tối ưu hóa

Đây không phải là lần đầu tiên ai đó đánh bại tôi tại CJam. Và không phải là lần đầu tiên bạn làm điều đó, mặc dù không chắc bạn đã từng làm điều đó trong cạnh tranh trực tiếp trước đó chưa.
aditsu

Heh :) Đó là tất cả về thuật toán :)
Trình tối ưu hóa

4

CJam - 70

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

Hãy thử nó tại http://cjam.aditsu.net/

Giải trình:

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

Các hnhà điều hành kiểm tra giá trị cuối cùng trên stack mà không loại bỏ nó. Nếu một vụ lở đất xảy ra, giá trị là mảng vách đá, được đánh giá là đúng vì nó không trống. Nếu không, giá trị cuối cùng là 0 (sai).
Vì vậy, trong trường hợp trượt lở, vòng lặp tiếp tục với mảng trên ngăn xếp, nếu không, nó kết thúc bằng 0 được đẩy sau mảng. Số 0 đó sau đó được xóa khỏi mảng bởi -toán tử tiếp theo .


4

Con trăn, 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)

Phiên bản mở rộng:

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)

Chỉnh sửa: Sau khi tối ưu hóa, tôi đã loại bỏ việc chấm dứt vòng lặp khó xử thông qua ngắt (tiết kiệm 1 byte). Cũng thay đổi slide từ lát dựa trên vòng lặp.


Tốt đẹp! Bạn có thể thả dấu ngoặc vuông bên trong sumcho 2 byte. Ngoài ra, thường là tốt hơn để xác định một chương trình đầy đủ trong Python, lấy đầu vào h,c=input()và in kết quả cuối cùng.
Zgarb

Tôi đã không nhận thấy giải pháp này và đã đăng bài kém hơn một chút của tôi D: Ồ tốt, cạnh tranh là tốt. Có lẽ tôi sẽ xem liệu tôi có thể cạo một số byte từ tôi không. Nhân tiện, lật các so sánh của bạn trong sumcó thể giúp bạn tiết kiệm được một : sum(h>i>0for i in q).
undergroundmonorail

@undergroundmonorail Tôi đã cố gắng hết sức, nhưng tôi sợ cách tiếp cận của bạn đơn giản là vượt trội :(. c=0tiết kiệm một byte (tôi không thể nhận xét về câu trả lời của bạn).
Philipp

4

Python 2 - 194 158 byte

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)

(Lưu ý rằng trình thông dịch đánh dấu của SE chuyển đổi các tab bằng chữ thành 4 khoảng trắng. Dòng 7 và 8 của chương trình này chỉ có một tab duy nhất [tức là một byte] thụt lề mỗi cái.)

Đưa đầu vào trên stdin, hđầu tiên. Ví dụ:

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

Chương trình này đã được thông qua rất nhiều cải tiến. Tôi đã chỉnh sửa câu trả lời này để giải thích một số chỉnh sửa quan trọng hơn, nhưng nó đã trở nên khá dài. Bạn có thể kiểm tra lịch sử chỉnh sửa nếu bạn tò mò.

Giải trình

Đầu tiên, hcđược đọc từ stdin. Trong Python 2, input()tương đương với eval(raw_input()), đó là lý do tại sao tôi yêu cầu một dấu phẩy phân tách các số.input()trả về một bộ dữ liệu ints, không cần chuyển đổi.

Tiếp theo, một danh sách các số nguyên được thực hiện. Nó 2*hdài Nửa đầu là hvà nửa sau là 0. Tôi không có bất kỳ lý do nào để chỉ ra rằng điều này là đủ để mô phỏng hs vô hạn ở bên trái và 0 ở bên phải. Tôi chỉ vấp vào nó và nó hoạt động cho tất cả các trường hợp thử nghiệm, vì vậy nếu ai đó có thể tìm thấy đầu vào thì nó không hoạt động vì tôi sẵn sàng thay đổi nó. Dù sao, danh sách này được gọi l, nhưng một bản sao khác của nó được gọi b.

bGiá trị của nó không thực sự quan trọng, tất cả vấn đề là nó là sự thật. Một danh sách không trống là trung thực và cách duy nhất bcó thể trống ở đây là nếu hlà 0, trong trường hợp đó, câu trả lời đúng vẫn được in. Trong mọi trường hợp khác, bphải trung thực để đảm bảo chúng tôi vào while b:vòng lặp. Tuy nhiên, điều đầu tiên xảy ra trong vòng lặp là đặt bthành 0, một giá trị falsey. Trong mỗi lần lặp lại của vòng lặp bphải được đặt lại cụ thể thành vòng lặp trung thực hoặc vòng lặp sẽ kết thúc.

Phần còn lại của vòng lặp là mô phỏng thực tế. Nó rất ngây thơ, về cơ bản chỉ là một bản dịch mã của mô tả vấn đề. Nếu bất kỳ yếu tố llà hơn clớn hơn một sau đó, nó được trừ bằng cvà tiếp theo cyếu tố có 1 thêm cho họ. (Nhân tiện, ma thuật bitwise được sử dụng ở đây chỉ là một cách viết ngắn hơn i+1+j.) Trong khi thực hiện các phép biến đổi này, bđược đặt thành 1. Lần đầu tiên không có phép biến đổi nào được thực hiện, bsẽ giữ nguyên 0 và vòng lặp chấm dứt.

Bất kỳ biểu thức đúng nào cũng ước tính Truevà khi bạn cố gắng làm toán trên Truenó sẽ ước tính thành 1. Điều tương tự cũng đúng Falsevà 0. Dòng cuối cùng của chương trình sử dụng mọi phần tử lnhư etrong biểu thức h>e>0và tính tổng kết quả. Điều này nhận được số lượng cột lớn hơn 0 nhưng thấp hơn chiều cao vách đá ban đầu, đó là giá trị mà câu hỏi yêu cầu. Nó được in và chương trình thoát.


2
Không c-=ctương đương với c=0?
Zgarb

... wow. cảm ơn vì đã theo dõi tôi, tôi nên bắt được điều đó, haha
ngầm cá nhân

1
i+1+j có thể được viết như i-~j
Sp3000

@ Sp3000 Tôi hoàn toàn quên mất phép thuật bitwise! Thanks: D
undergroundmonorail

3

Haskell, 163 156 151 byte

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)

Cách sử dụng : h#c, ví dụ: 6#2đầu ra nào4 .

Cách thức hoạt động: chức năng của người trợ giúp sthực hiện một vụ lở đất. Áp dụng nhiều lầns cho đến khi đầu ra không thay đổi nữa. Đếm các yếu tố bị ảnh hưởng.

Tìm thấy chức năng "áp dụng cho đến khi đầu ra không thay đổi" (nghĩa là until=<<((==)=<<)) tại Stackoverflow .


Bạn có thể lưu một vài byte bằng cách định nghĩa flà infix ( h#c=...) và di chuyển wheremệnh đề vào cùng một dòng. Ngoài ra, vẫn còn một số dấu ngoặc đơn để sử dụng $, mặc dù tôi không chắc có bao nhiêu ...
Zgarb

@Zgarb: cảm ơn vì những gợi ý. Thay thế ()bằng $là dấu vết và lỗi cho tôi.
nimi

3

Toán học, 108 104 100 97 95

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

Sử dụng:

f[c, h]

Thí dụ:

f[5, 80]

28


2

C # 303 295

Nó hoạt động!

Nhưng nó là một ....

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;}

Tôi phải tìm ngôn ngữ mới;)

Tôi sẽ kiểm tra thứ này của CJam ...

Cải thiện:

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
Bạn vẫn có thể tối ưu hóa điều này một chút. int z=i;int y=i-1;có thể int z=i,y=i-1;. Các forvòng lặp không làm những điều phức tạp với chỉ số của chúng, vì vậy, ví dụ for(int i=s.Count-1;i>0;i--)có thể for(int i=s.Count;--i>0;). 1<0là một cách viết ngắn hơn false. Tôi nghi ngờ rằng if(s[s.Count-1]>0)s.Add(0);có thể mất điều kiện mà không ảnh hưởng đến tính chính xác, chỉ cần tốc độ.
Peter Taylor

@Peter Taylor. Cảm ơn!
mike m
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.