산사태 예측


22

산사태

이 도전에서 당신의 임무는 대규모 산사태로 인한 피해 정도를 예측하는 것입니다. 초기 높이 h >= 0임계 계수로 매개 변수화 된 다음의 단순화 된 2 차원 모델을 사용합니다 c > 0. 높이 절벽으로 시작 h하면 지형이 왼쪽과 오른쪽으로 무한히 평평하다고 가정합니다. 대한 h = 6이 같은 상황 외모 :

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

-부동산 암반, 그리고는 #불안정한 토양이다. 두 개의 인접한 열 사이의 높이 차이가 이상이면 c하는 사태가 발생 맨 c좌측 열에서 토양의 단위는 옆으로 넘어 c오른쪽 각 하나에 열. 그림에서 가장 오른쪽에 비어 있지 않은 열은 불안정 c = 2하므로 산사태가 발생합니다.

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

기둥이 여전히 불안정하여 두 번째 산사태가 발생합니다.

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

이제 왼쪽의 기둥이 불안정 해지면서 새로운 산사태가 발생합니다.

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

그 후 절벽은 다시 안정됩니다. 이 모델의 좋은 점은 산사태가 처리되는 순서가 중요하지 않다는 것입니다. 최종 결과는 같습니다.

작업

프로그램에는 정수 매개 변수 hc입력 이 제공되며 (순서는 중요하지 않지만 답변에 지정해야 함) 산사태에 영향을 미치는 총 수를 출력해야합니다 . 이것은 높이 사이 엄격 결과 안정된 절벽의 열 개수 수단 0h. 위의 예에서 올바른 출력은 4입니다.

전체 프로그램이나 함수를 작성할 수 있습니다. 가장 낮은 바이트 수가 이기고 표준 허점은 허용되지 않습니다.

테스트 사례

이것들은 형식으로 제공됩니다 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";

여기에서 온라인으로 사용해보십시오


다시
실패

@aditsu 다시?
Optimizer

누군가가 CJam에서 나를 때리는 것은 처음이 아닙니다. 그리고 당신이 전에 직접 경쟁에서 해본 적이 있는지 확실하지 않지만, 당신이 그것을하고있는 첫 번째 일은 아닙니다.
aditsu

Heh :) 알고리즘에 관한 모든 것 :)
Optimizer

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연산자를 제거없이 스택에 마지막 값을 체크한다. 산사태가 발생하면 값은 절벽 배열이며 비어 있지 않기 때문에 true로 평가됩니다. 그렇지 않은 경우 마지막 값은 0 (거짓)입니다.
따라서 산사태의 경우 루프는 스택의 배열에서 계속되고, 그렇지 않으면 배열 다음에 0이 눌려집니다. 그런 다음 0은 다음 -연산자에 의해 배열에서 제거됩니다 .


4

파이썬 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)

편집 : 최적화 후, break (1 바이트 절약)를 통해 어색한 루프 종료를 제거했습니다. 슬라이드를 슬라이스 기반에서 루프 기반으로 변경했습니다.


좋은! 대괄호 안에 sum2 바이트를 넣을 수 있습니다 . 또한 일반적으로 파이썬으로 전체 프로그램을 정의 h,c=input()하여 결과 를 입력 하고 최종적으로 인쇄하는 것이 좋습니다.
Zgarb

나는이 해결책을 알지 못하고 약간 더 나쁜 D를 게시했습니다. 오, 경쟁은 좋습니다. 어쩌면 내가 약간의 바이트를 면도 할 수 있는지 볼 수 있습니다. 그건 그렇고, 당신의 비교를 뒤집 으면 sum하나를 구할 수 있습니다 sum(h>i>0for i in q).
undergroundmonorail

내가 열심히 노력 @undergroundmonorail,하지만 난 당신의 접근 방식은 :( 단순히 우수 우려하고있다. c=0바이트를 저장 (내가 할 수있는 대답에하지 코멘트).
필립

4

파이썬 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)

(SE의 마크 다운 인터프리터는 리터럴 탭을 4 개의 공백으로 변환합니다.이 프로그램의 7 행과 8 행에는 각각 단일 탭 (즉, 1 바이트)의 들여 쓰기 만 있습니다.)

h먼저 stdin에 입력을 받습니다. 예를 들면 다음과 같습니다.

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

이 프로그램은 많은 개선을 통해 이루어졌습니다. 더 많은 주요 편집 내용을 설명하기 위해이 답변을 편집했지만 시간이 오래 걸렸습니다. 궁금하다면 편집 기록을 확인할 수 있습니다.

설명

첫째, hc표준 입력에서 읽습니다. 파이썬 2에서는와 input()동일 eval(raw_input())하므로 숫자를 구분하는 쉼표를 요청하는 이유입니다. input()제공은 변환이 필요없는 int의 튜플을 반환합니다.

다음으로 정수 목록이 작성됩니다. 그것은이다 2*h오래. 첫 번째 반은 h두 번째 반은 0입니다. 나는 이것이 h왼쪽으로 무한대를 시뮬레이션 하고 오른쪽으로 0을 시뮬레이션하기에 충분하다는 것을 보여줄만한 근거가 없습니다 . 나는 그저 그것에 넘어졌고 모든 테스트 사례에서 작동하므로 누군가가 입력을 찾을 수 없다면 작동하지 않습니다. 나는 기꺼이 그것을 바꿀 것입니다. 어쨌든이 목록을이라고 l하지만 다른 사본을이라고 b합니다.

b의 가치는 실제로 중요하지 않습니다. 중요한 것은 그것이 진실하다는 것입니다. 비어 있지 않은 목록은 진실이며 b여기서 비어 있는 유일한 방법 h은 0 인 경우 정답이 계속 인쇄됩니다. 다른 경우 b에는 while b:루프에 들어가기 위해 진실해야합니다 . 그러나 루프에서 가장 먼저 발생 b하는 것은 잘못된 값인 0 으로 설정 하는 것입니다. 루프를 반복 할 때마다 b구체적으로 다시 설정해야합니다. 그렇지 않으면 루프가 종료됩니다.

루프의 나머지 부분은 실제 시뮬레이션입니다. 본질적으로 문제 설명을 코드로 변환하는 것만으로 매우 순진합니다. 의 요소가 그 뒤의 요소 l보다 c크면 c, 그 c요소를 빼고 다음 요소에 1을 더합니다. (여기서 사용 된 비트 단위의 마법은 단지 짧은 쓰기 i+1+j방법입니다.) 이러한 변환을 수행하는 동안 b1로 설정됩니다. 처음으로 변환을 수행하지 않으면 b0을 유지하고 루프가 종료됩니다.

모든 실제 표현식은로 평가되고 True수학을 시도 할 때 True1로 평가됩니다. 동일한 것은 False0입니다. 프로그램의 마지막 행은 표현식에서 와 l같이 모든 요소를 ​​사용 하고 결과를 합산합니다. 이것은 0보다 크지 만 원래 절벽 높이보다 낮은 열 수를 얻습니다. 이는 질문이 요구하는 값입니다. 인쇄되고 프로그램이 종료됩니다.eh>e>0


2
하지인가 c-=c에 해당 c=0?
자가 브

...와우. 내 등을 봐 주셔서 감사합니다.
undergroundmonorail

1
i+1+j다음과 같이 쓸 수 있습니다i-~j
Sp3000

@ Sp3000 나는 비트 마법에 대해 완전히 잊었다! 고마워
undergroundmonorail

3

하스켈 163 156 151 바이트

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#c6#2를 들어 어떤 출력 4.

작동 방식 : 도우미 기능 s은 단일 산사태를 수행합니다. s출력이 더 이상 변경되지 않을 때까지 반복해서 적용 하십시오. 영향을받는 요소를 세십시오.

"출력이 변경되지 않을 때까지 적용"기능을 찾았습니다 (예 : until=<<((==)=<<)Stackoverflow 에서 .


finfix ( h#c=...) 로 정의 하고 where절을 동일한 행으로 이동하여 몇 바이트를 저장할 수 있습니다 . 또한 몇 개의 괄호가 있지만 아직 몇 개인 $지 잘 모르겠습니다.
Zgarb

@ Zgarb : 힌트 주셔서 감사합니다. 나를 대체 ()하는 $것은 흔적과 오류입니다.
nimi

3

매쓰, 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;. for예를 들어, 그래서 루프는, 자신의 지표로 일을 복잡하게하지 않는 for(int i=s.Count-1;i>0;i--)for(int i=s.Count;--i>0;). 1<0더 짧은 글쓰기 방법입니다 false. 나는 if(s[s.Count-1]>0)s.Add(0);정확성, 속도에 영향을 미치지 않고 상태를 잃을 수 있다고 생각합니다 .
피터 테일러

@ 피터 테일러. 감사!
mike m
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.