Tìm mảng chạy


14

Tìm các bước chạy trong một mảng

Một lần chạy được định nghĩa là ba hoặc nhiều số tăng so với trước đó với một bước không đổi. Ví dụ: [1,2,3] sẽ là một bước chạy với bước 1, [1,3,5,7] sẽ là một bước chạy với bước 2 và [1,2,4,5] không phải là một bước chạy.

Chúng ta có thể diễn tả các lần chạy này bằng ký hiệu "i to j by s" trong đó i là số đầu tiên của lần chạy, j là số cuối cùng của lần chạy và s là bước. Tuy nhiên, các bước của bước 1 sẽ được thể hiện "i to j".

Vì vậy, bằng cách sử dụng các mảng trước, chúng tôi nhận được:

  • [1,2,3] -> "1 đến 3"

  • [1,3,5,7] -> "1to7by2"

  • [1,2,4,5] -> "1 2 4 5"

Trong thử thách này, nhiệm vụ của bạn là làm điều này cho các mảng có thể có nhiều lần chạy.

Ví dụ mã Python với đệ quy:

def arr_comp_rec(a, start_index):
    # Early exit and recursion end point
    if start_index == len(a)-1:
        return str(a[-1])
    elif start_index == len(a):
        return ''

    # Keep track of first delta to compare while searching
    first_delta = a[start_index+1] - a[start_index]
    last = True
    for i in range(start_index, len(a)-1):
        delta = a[i+1] - a[i]
        if delta != first_delta:
            last = False
            break
    # If it ran through the for loop, we need to make sure it gets the last value
    if last: i += 1

    if i - start_index > 1:
        # There is more than 2 numbers between the indexes
        if first_delta == 1:
            # We don't need by if step = 1
            return "{}to{} ".format(a[start_index], a[i]) + arr_comp_rec(a, i+1)
        else:
            return "{}to{}by{} ".format(a[start_index], a[i], first_delta) + arr_comp_rec(a, i+1)
    else:
        # There is only one number we can return
        return "{} ".format(a[start_index]) + arr_comp_rec(a, i)

IO rất linh hoạt

Đầu vào

Mảng các số nguyên dương được sắp xếp (không trùng lặp)

Đầu ra

Chuỗi các lần chạy cách nhau bởi một khoảng trắng hoặc một chuỗi chuỗi của các lần chạy

Không cần phải tham lam theo một hướng cụ thể

Có thể có khoảng trắng ở cuối

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

In: [1000, 1002, 1004, 1006, 1008, 1010]
Out: "1000to1010by2"

In: [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
Out: "1to3 5 8 13 21 34 55 89 144 233"

In: [10, 20, 30, 40, 60]
Out: "10to40by10 60"

In: [5, 6, 8, 11, 15, 16, 17]
Out: "5 6 8 11 15to17"

In: [1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 15, 30, 45, 50, 60, 70, 80, 90, 91, 93]
Out: "1to7 9to15by2 30 45 50to90by10 91 93"

Đây là nên số byte thắng ít nhất.



2
Nó phải tham lam từ trái sang phải? (tức là [4, 5, 6, 7, 9, 11, 13, 15]không thể 4to6 7to15by2?)
Jonathan Allan

1
@Jonathan ALLan Không, không nhất thiết phải để lại sự tham lam.
WretchedLout

Tôi cho rằng sẽ không có mục trùng lặp?
Shieru Asakoto

1
Chỉ có số nguyên dương. @ Οurous Trailing khoảng trắng chấp nhận được.
Khốn khổ

Câu trả lời:


5

Thạch ,  42  40 byte

-2 nhờ Kevin Cruijssen (lọc ra twos ḟ2, thay vì thay thế twos bằng số không, 2,0y)

ŒṖIE×LƲ€ḟ2SƊÞṪµ.ịU,Iḟ1ƊQ€Fż“to“by”ṁṖƊ$)K

Một chương trình đầy đủ in kết quả.
(Là một liên kết đơn âm, một danh sách chứa hỗn hợp các số nguyên và ký tự sẽ được tạo ra)

Hãy thử trực tuyến!
(Quá kém hiệu quả để trường hợp thử nghiệm lớn nhất hoàn thành trong vòng 60 giây, vì vậy tôi đã xóa[1,2,3,4].)

Làm sao?

ŒṖIE×LƲ€ḟ2SƊÞṪµ.ịU,Iḟ1ƊQ€Fż“to“by”ṁṖƊ$)K - Main Link: list of numbers
ŒṖ                                       - all partitions
           ƊÞ                            - sort by last three links as a monad:
      Ʋ€                                 -   last four links as a monad for €ach:
  I                                      -     incremental differences (of the part)
   E                                     -     all equal?
     L                                   -     length (of the part)
    ×                                    -     multiply
        ḟ2                               -   filter discard twos
          S                              -   sum
             Ṫ                           - tail (gets us the desired partition of the input)
              µ                       )  - perform this monadic chain for €ach:
               .                         -   literal 0.5
                ị                        -   index into (the part) - getting [tail,head]
                 U                       -   upend - getting [head,tail]
                      Ɗ                  -   last three links as a monad:
                   I                     -     incremental differences (of the part)
                     1                   -     literal one
                    ḟ                    -     filter discard (remove the ones)
                  ,                      -   pair -> [[head,tail],[deltasWithoutOnes]]
                       Q€                -   de-duplicate €ach -> [[head,tail],[delta]] or [[head,tail],[]] or [[loneValue],[]]
                         F               -   flatten -> [head,tail,delta] or [head,tail] or [loneValue]
                                     $   -   last two links as a monad:
                                    Ɗ    -     last three links as a monad:
                           “to“by”       -       literal list [['t', 'o'], ['b', 'y']]
                                   Ṗ     -       pop (get flattened result without rightmost entry)
                                  ṁ      -       mould ["to","by"] like that (i.e. ["to","by"] or ["to"] or [])
                         ż               -     zip together      
                                       K - join with spaces
                                         - implicit print

'by' không nên được sử dụng nếu bước = 1
WretchedLout

oh Gawwwd: p Cảm ơn bạn đã ủng hộ!
Jonathan Allan

2,0ySƲÞcó thể được đánh gôn tới ḟ2SƊÞ-2 byte.
Kevin Cruijssen

@KevinCruijssen rất đúng, golf đẹp, cảm ơn
Jonathan Allan

1
@KevinCruijssen FYI Tôi nhớ tại sao bây giờ lại có - ban đầu tôi đang cố gắng phân loại với một sản phẩm P, thay vì một khoản tiền Svà sẽ cần các số không.
Jonathan Allan

6

Swift, 246 byte

func f(_ a:[Int]){
var c=a.count,m=a+a,z=0,r:String=""
for i in 1..<c{m[i]-=a[i-1];if m[i]==m[i-1]{m[i-1]=0}};m[0]=1
for i in 0..<c{if m[i]==0 {z=1}else if z==0{r+=" \(a[i])"}else{r+="to\(a[i])"+(m[i]>1 ? "by\(m[i])":"");z=0;m[i+1]=1}}
print(r)
}

Hãy thử trực tuyến!


4
Chào mừng bạn đến với Câu đố lập trình & Code Golf! Câu trả lời đầu tiên rất hay. Tôi hy vọng bạn sẽ ở lại vì cộng đồng Swift ở đây ... thực sự rất nhỏ!
Ông Xcoder



3

JavaScript (ES6), 129 byte

Trả về một chuỗi các chuỗi.

a=>(a.map((n,i)=>n+[n-a[i+1]||''])+'').replace(/(\d+)(-\d+)(?:,\d+\2)+,(\d+)/g,(_,a,b,c)=>a+'to'+(~b?c+'by'+-b:c)).split(/-\d+,/)

Hãy thử trực tuyến!

Làm sao?

Bước 1

Trước tiên, chúng tôi thêm vào mỗi số một hậu tố bao gồm một đầu dẫn '-'theo sau là sự khác biệt với số tiếp theo, ngoại trừ mục cuối cùng không thay đổi. Mảng mới này bị ép buộc thành một chuỗi.

(a.map((n, i) => n + [n - a[i + 1] || '']) + '')

Thí dụ:

Input : [ 1, 2, 3, 5, 9, 11, 13, 20 ]
Output: "1-1,2-1,3-2,5-4,9-2,11-2,13-7,20"

Bước 2

Chúng tôi xác định tất cả các lần chạy trong chuỗi kết quả và thay thế chúng bằng ký hiệu thích hợp.

.replace(
  /(\d+)(-\d+)(?:,\d+\2)+,(\d+)/g,
  (_, a, b, c) => a + 'to' + (~b ? c + 'by' + -b : c)
)

Thí dụ:

Input : "1-1,2-1,3-2,5-4,9-2,11-2,13-7,20"
Output: "1to3-2,5-4,9to13by2-7,20"

Bước 3

Cuối cùng, chúng tôi chia chuỗi trên các hậu tố còn lại, bao gồm cả dấu phẩy.

.split(/-\d+,/)

Thí dụ:

Input : "1to3-2,5-4,9to13by2-7,20"
Output: [ '1to3', '5', '9to13by2', '20' ]

2

Hồng ngọc , 125 118 byte

->a{i=y=0;a.chunk{|x|-y+y=x}.map{|z,w|2-i<(s=w.size)?"#{w[i*s]}to#{w[~i=0]}"+"by#{z}"*(z<=>1)+' ':' '*i+w*' '*i=1}*''}

Hãy thử trực tuyến!

Giải trình

Ruby's Enumerable có một chunkphương thức hữu ích thực hiện chính xác những gì chúng ta cần ở đây - nhóm các mục theo các lần chạy liên tiếp có cùng giá trị trả về từ khối, trong trường hợp của chúng tôi - sự khác biệt giữa hiện tại ( x) và trước đó (y ).

Thông báo trước là chiến lược như vậy sẽ không nắm bắt được yếu tố đầu tiên của hoạt động, ví dụ ở đây chỉ có hai yếu tố cuối cùng được nhóm lại với nhau:

Input: [5, 6, 8, 11, 15, 16, 17]
Grouped: [[5, [5]], [1, [6]], [2, [8]], [3, [11]], [4, [15]], [1, [16, 17]]]

Do đó, trong khi ánh xạ tới các chuỗi được định dạng chính xác, khi chúng tôi gặp một lần chạy tiềm năng mới (chunk với> 1 mục), chúng tôi phải theo dõi nếu mục trước đó là đơn ( i=1) hoặc đã được sử dụng trong lần chạy khác ( i=0). Nếu có một mục duy nhất không được sử dụng, nó sẽ trở thành điểm bắt đầu của hoạt động và giảm ngưỡng kích thước khối từ 3 xuống 2.


2

R , 180 175 byte

r=rle(c(0,diff(a<-scan())));for(j in 1:sum(1|r$l)){l=r$l[j];v=r$v[j];i=T+l-1;cat("if"(l>2-F,paste0(a[T][!F],"to",a[i],"by"[v>1],v[v>1]," "),c("",a[T:i])[-3^F]));T=i+1;F=l<3-F}

Hãy thử trực tuyến!

Về mặt khái niệm, đây là một cổng của câu trả lời Ruby của tôi , mặc dù rõ ràng là khá khác biệt về mặt kỹ thuật.

5 byte được lưu bởi JayCe.


Tôi muốn làm một cái gì đó với rlenhưng quá lười biếng ... bạn có thể tiết kiệm 1 byte sum(1|x)thay cho length(x): TIO
JayCe

Trên thực tế, bạn có thể chỉ có 1 cat cho 175 byte: TIO
JayCe

Ah, tuyệt, cảm ơn!
Kirill L.

2

R , 238 217 byte

Cảm ơn @digEmAll cho -19 byte.

function(v,R=rle(diff(v)),L=R$l,S=sum(L|1),Y=0)if(!S)cat(v)else for(i in 1:S){D=R$v[i]
N=L[i]-F
if(N>1){N=N+1
cat(v[Y+1],'to',v[Y+N],'by'[D>1],D[D>1],' ',sep='')
F=1}else{N=N+(i==S)
if(N>0)cat(v[Y+1:N],'')
F=0}
Y=Y+N}

Hãy thử trực tuyến!


sử dụng Fthay vì nnhư nó đã được khởi tạo 0, nó sẽ tiết kiệm một vài byte, tôi nghĩ vậy.
Giuseppe

Điều này là bực bội. Bạn đang ở gần đó chỉ bằng cách sử dụng split, diffrle. Thật không may, tìm kiếm tham lam cho chạy có nghĩa là rất nhiều khó khăn.
J.Doe

214 byte Hầu như ở đó, vấn đề duy nhất là đôi khi khoảng cách không chính xác ...
digEmAll

Đó 'by'[D>1]là một mẹo hay.
J.Doe

Điều này dường như hoạt động tốt 217 byte
digEmAll


1

Sạch , 208 ... 185 byte

import StdEnv,Data.List,Text
l=length
$[]=""
$k=last[u<+(if(v>[])("to"<+last v<+if(u<v!!0-1)("by"<+(v!!0-u))"")"")+" "+ $t\\i=:[u:v]<-inits k&t<-tails k|l(nub(zipWith(-)i v))<2&&l i<>2]

Hãy thử trực tuyến!



1

Python 2 , 170 166 byte

def f(a):
 j=len(a)
 while j>2:
	l,r=a[:j:j-1];s=(r-l)/~-j
	if a[:j]==range(l,r+1,s):return[`l`+'to%d'%r+'by%d'%s*(s>1)]+f(a[j:])
	j-=1
 return a and[`a[0]`]+f(a[1:])

Hãy thử trực tuyến!


Tôi không chắc định dạng đầu ra này có hợp lệ không; tất cả các chuỗi nên là chuỗi, không?
Erik the Outgolfer

@EriktheOutgolfer Đã sửa lỗi
TFeld


1

mã byte gvm (cam kết 2612106 ), 108 byte

Yêu cầu kích thước của mảng trong một dòng, sau đó các thành viên mỗi dòng trong một dòng.

Hexdump:

> hexdump -C findruns.bin
00000000  e1 0a 00 10 00 e1 0b 00  ff c8 92 00 f4 f7 10 00  |................|
00000010  01 b0 20 03 00 ff 0a 01  a2 01 c8 92 00 f4 01 c0  |.. .............|
00000020  03 00 ff 0a 02 d0 72 01  0a 03 c8 92 00 f4 05 b0  |......r.........|
00000030  20 a2 02 c0 02 02 6a 03  8b 00 ff f6 06 b0 20 a2  | .....j....... .|
00000040  02 f4 ce 0a 02 c8 92 00  f6 07 6a 03 8b 00 ff f6  |..........j.....|
00000050  f2 b9 66 01 a2 02 00 01  8a 03 f6 05 b9 69 01 a2  |..f..........i..|
00000060  03 92 00 f4 ac c0 74 6f  00 62 79 00              |......to.by.|
0000006c

Chạy thử:

> echo -e "7\n5\n6\n8\n11\n15\n16\n17\n" | ./gvm findruns.bin
5 6 8 11 15to17
> echo -e "20\n1\n2\n3\n4\n5\n6\n7\n9\n11\n13\n15\n30\n45\n50\n60\n70\n80\n90\n91\n93\n" | ./gvm findruns.bin
1to7 9to15by2 30 45 50to90by10 91 93

Lắp ráp thủ công từ đây:

0100  e1        rud                     ; read length of array
0101  0a 00     sta     $00             ; -> to $00
0103  10 00     ldx     #$00            ; loop counter
                  readloop:
0105  e1        rud                     ; read unsigned number
0106  0b 00 ff  sta     $ff00,x         ; store in array at ff00
0109  c8        inx                     ; next index
010a  92 00     cpx     $00             ; length reached?
010c  f4 f7     bne     readloop        ; no -> read next number
010e  10 00     ldx     #$00            ; loop counter
0110  01                                ; 'lda $20b0', to skip next instruction
                  runloop:
0111  b0 20     wch     #' '            ; write space character
0113  03 00 ff  lda     $ff00,x         ; load next number from array
0116  0a 01     sta     $01             ; -> to $01
0118  a2 01     wud     $01             ; and output
011a  c8        inx                     ; next index
011b  92 00     cpx     $00             ; length reached?
011d  f4 01     bne     compare         ; if not calculate difference
011f  c0        hlt                     ; done
                  compare:
0120  03 00 ff  lda     $ff00,x         ; load next number from array
0123  0a 02     sta     $02             ; -> to $01
0125  d0        sec                     ; calculate ...
0126  72 01     sbc     $01             ; ... difference ...
0128  0a 03     sta     $03             ; ... to $03
012a  c8        inx                     ; next index
012b  92 00     cpx     $00             ; length reached?
012d  f4 05     bne     checkrun        ; if not check whether we have a run
012f  b0 20     wch     #' '            ; output space
0131  a2 02     wud     $02             ; output number
0133  c0        hlt                     ; done
                  checkrun:
0134  02 02     lda     $02             ; calculate next ...
0136  6a 03     adc     $03             ; ... expected number in run
0138  8b 00 ff  cmp     $ff00,x         ; compare with real next number
013b  f6 06     beq     haverun         ; ok -> found a run
013d  b0 20     wch     #' '            ; otherwise output space ...
013f  a2 02     wud     $02             ; ... and number
0141  f4 ce     bne     runloop         ; and repeat searching for runs
                  haverun:
0143  0a 02     sta     $02             ; store number to $02
0145  c8        inx                     ; next index
0146  92 00     cpx     $00             ; length reached?
0148  f6 07     beq     outputrun       ; yes -> output this run
014a  6a 03     adc     $03             ; calculate next expected number
014c  8b 00 ff  cmp     $ff00,x         ; compare with real next number
014f  f6 f2     beq     haverun         ; ok -> continue parsing run
                  outputrun:
0151  b9 66 01  wtx     str_to          ; write "to"
0154  a2 02     wud     $02             ; write end number of run
0156  00 01     lda     #$01            ; compare #1 with ...
0158  8a 03     cmp     $03             ; ... step size
015a  f6 05     beq     skip_by         ; equal, then skip output of "by"
015c  b9 69 01  wtx     str_by          ; output "by"
015f  a2 03     wud     $03             ; output step size
                  skip_by:
0161  92 00     cpx     $00             ; length of array reached?
0163  f4 ac     bne     runloop         ; no -> repeat searching for runs
0165  c0        hlt                     ; done
                  str_to:
0166  74 6f 00                          ; "to"
                  str_by:
0169  62 79 00                          ; "by"
016c

1

05AB1E (di sản) , 49 50 byte

.œʒε¥Ë}P}Σ€g2KO>}¤εD©g≠i¬s¤„toý¬®¥0èDU≠i„byX««]˜ðý

Quá dài, nhưng tôi rất vui vì nó hoạt động. Thử thách này khó hơn rất nhiều so với vẻ ngoài của nó .. Có thể không nghi ngờ gì nữa có thể bị đánh gôn hơn nữa.
Σ€g2KO>}¤là một cảng 2,0ySƲÞṪ từ @JonathanAllan Jelly câu trả lời 's (nhờ!).

Hãy thử trực tuyến. (LƯU Ý: Đã hết thời gian cho các trường hợp thử nghiệm lớn.)

+1 byte dưới dạng sửa lỗi vì 0luôn được đặt ở vị trí theo sau khi sắp xếp.

Giải trình:

                       # Get all partions of the (implicit) input-list
                         #  i.e. [1,2,3,11,18,20,22,24,32,33,34]
                         #   → [[[1],[2],[3],[11],[18],[20],[22],[24],[32],[33],[34]],
                         #      [[1],[2],[3],[11],[18],[20],[22],[24],[32],[33,34]],
                         #      [[1],[2],[3],[11],[18],[20],[22],[24],[32,33],[34]],
                         #      ...]
  ʒ     }                # Filter this list by:
   ε  }                  #  Map the current sub-list by:
    ¥Ë                   #   Take the deltas, and check if all are equal
                         #    i.e. [1,2,3] → [1,1] → 1
                         #    i.e. [1,2,3,11] → [1,1,8] → 0
       P                 #  Check if all sub-list have equal deltas
  Σ      }               # Now that we've filtered the list, sort it by:
   g                    #  Take the length of each sub-list
                         #   i.e. [[1,2,3],[11,18],[20,22,24],[32,33],[34]]
                         #    → [3,2,3,2,1]
                         #   i.e. [[1,2,3],[11],[18,20,22,24],[32,33,34]]
                         #    → [3,1,4,3]
     2K                  #  Remove all 2s
                         #   i.e. [3,2,3,2,1] → ['3','3','1']
       O                 #  And take the sum
                         #   i.e. ['3','3','1'] → 7
                         #   i.e. [3,1,4,3] → 11
        >                #  And increase the sum by 1 (0 is always trailing when sorting)
          ¤              # And then take the last item of this sorted list
                         #  i.e. for input [1,2,3,11,18,20,22,24,32,33,34]
                         #   → [[1,2,3],[11],[18,20,22,24],[32,33,34]]
  ε                      # Now map each of the sub-lists to:
   D©                    #  Save the current sub-list in the register
     gi                 #  If its length is not 1:
                         #    i.e. [11] → 1 → 0 (falsey)
                         #    i.e. [18,20,22,24] → 4 → 1 (truthy)
        ¬s¤              #   Take the head and tail of the sub-list
                         #    i.e. [18,20,22,24] → 18 and 24
           toý          #   And join them with "to"
                         #    i.e. 18 and 24 → ['18to24', '18to20to22to24']
               ¬         #   (head to remove some access waste we no longer need)
                         #    i.e. ['18to24', '18to20to22to24'] → '18to24'
        ®                #   Get the sub-list from the register again
         ¥               #   Take its deltas
                         #    i.e. [18,20,22,24] → [2,2,2]
          0è             #   Get the first item (should all be the same delta)
                         #    i.e. [2,2,2] → 2
            DU           #   Save it in variable `X`
              i         #   If the delta is not 1:
                         #     i.e. 2 → 1 (truthy)
                byX«    #    Merge "by" with `X`
                         #     i.e. 2 → 'by2'
                     «   #    And merge it with the earlier "#to#"
                         #     i.e. '18to24' and 'by2' → '18to24by2'
                      ]  # Close the mapping and both if-statements
˜                        # Flatten the list
                         #  i.e. ['1to3',[11],'18to24by2','32to34']
                         #   → ['1to3',11,'18to24by2','32to34']
 ðý                      # And join by spaces (which we implicitly output as result)
                         #  i.e. ['1to3',11,'18to24by2','32to34']
                         #   → '1to3 11 18to24by2 32to34'

0

Perl 5 , 154 byte

{my(@r,$r);@r&&(@$r<2||$$r[1]-$$r[0]==$_-$$r[-1])?push@$r,$_:push@r,$r=[$_]for@_;join" ",map@$_<3?@$_:("$$_[0]to$$_[-1]by".($$_[1]-$$_[0]))=~s/by1$//r,@r}

Tương tự với không gian, dòng mới, #comments và sub by:

sub by {
  my(@r,$r);
  @r &&                               # if at least one run candidate exists and...
   ( @$r<2                            # ...just one elem so far
     || $$r[1]-$$r[0] == $_-$$r[-1] ) # ...or diff is same
    ? push @$r, $_                    # then add elem to curr. run candidate
    : push @r, $r=[$_]                # else start new run cand. with curr elem
        for @_;
  join " ",
    map @$_<3                                         # is it a run?
    ? @$_                                             # no, just output the numbers
    : ("$$_[0]to$$_[-1]by".($$_[1]-$$_[0]))=~s/by1$//r, # yes, make run, delete by1
    @r                                                # loop run candidates
}

Hãy thử trực tuyến!

... để vượt qua các bài kiểm tra từ OP.


0

Võng mạc 0.8.2 , 77 byte

\d+
$*
(1+)(?= \1(1+))
$1:$2
1:(1+) (1+:\1 )+(1+)
1to$3by$1
:1+|by1\b

1+
$.&

Hãy thử trực tuyến! Liên kết bao gồm các trường hợp thử nghiệm. Giải trình:

\d+
$*

Chuyển đổi sang unary.

(1+)(?= \1(1+))
$1:$2

Tính toán sự khác biệt liên tiếp.

1:(1+) (1+:\1 )+(1+)
1to$3by$1

Chuyển đổi chạy sang to...by cú pháp.

:1+|by1\b

Loại bỏ sự khác biệt chưa được chuyển đổi và by1 .

1+
$.&

Chuyển đổi thành số thập phân.

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.