Mất bao lâu để vẽ một cây gậy?


12

(Dựa trên bài toán Math.SE này , cũng cung cấp một số đồ họa)

Tôi có một cây gậy trông giống như thế này:

nhập mô tả hình ảnh ở đây

Tôi muốn nó trông giống như thế này:

nhập mô tả hình ảnh ở đây

Tuy nhiên, tôi không phải là một họa sĩ chuyên gia, vì vậy trước khi tôi bắt đầu một dự án DIY đầy tham vọng như vậy, tôi muốn chắc chắn rằng tôi không nằm trong đầu mình.

Chương trình của bạn sẽ cho tôi biết có bao nhiêu bước liên quan đến việc vẽ cây gậy này. Mỗi bước liên quan đến việc sơn một khu vực liên tục với một màu đặc, bao phủ các lớp sơn trước đó. Ví dụ ở trên, tôi có thể sơn nửa màu xanh bên trái, nửa bên phải màu đỏ và sau đó hai khu vực màu xanh lá cây riêng biệt cho tổng cộng 4 bước (màu xanh lá cây không được sơn liên tục).

nhập mô tả hình ảnh ở đây

Đây là ASCII:

------
bbb---
bbbrrr
bgbrrr
bgbrgr

Có một vài cách khác nhau để vẽ thanh này và kết quả tương tự. Tôi chỉ quan tâm đến ước tính thời gian, tuy nhiên, đó là bốn bước.

Mục tiêu

Chương trình của bạn sẽ xuất ra số bước tối thiểu cần thiết để vẽ một cây gậy với bảng màu nhất định. Sơ đồ sơn sẽ ở dạng một chuỗi các ký tự, trong khi đầu ra sẽ là một số. Đây là mã golf. Chương trình ngắn nhất sẽ thắng.

Đầu vào

Chương trình của bạn sẽ nhận được sơ đồ tô màu cho một cây gậy dưới dạng một chuỗi các chữ cái. Mỗi chữ cái duy nhất (trường hợp nhạy cảm) đại diện cho một màu sắc duy nhất.

YRYGR

grG

GyRyGyG

pbgbrgrp

hyghgy

Đầu ra

Những con số này là số bước ít nhất cần thiết để vẽ các que.

4

3

4

5

4

Giải thích

Đây là cách tôi đến với những con số trên. Chương trình của bạn không cần xuất kết quả này:

 -----
 YYY--
 YRY--
 YRYG-
 YRYGR

 ---
 g--
 gr-
 grG

 -------
 GGGGGGG
 GyyyGGG
 GyRyGGG
 GyRyGyG

 --------
 pppppppp
 pbbbpppp
 pbbbrrrp
 pbgbrrrp
 pbgbrgrp

 ------
 -yyyyy
 -ygggy
 hygggy
 hyghgy

Chỉnh sửa: Tôi sẽ thêm nhiều trường hợp kiểm tra nếu chúng chứng minh là các trường hợp kiểm tra khó khăn hơn.


Điều này làm tôi nhớ đến stackoverflow.com/q/10364248/785745 , tương tự, nhưng ở dạng 2D.
Kendall Frey

Câu trả lời:


3

GolfScript, 82 72 67 ký tự

.,n*{:c,,{[).2$1<*\c>+1$.,,{).2$<\3$<=},,.@>@@>]}%\;{~S)}%$0+0=}:S~

Nhanh chóng hợp lý cho một chương trình GolfScript, ví dụ:

> hyghgy
4

> pbgbrgrp
5

Thuật toán được sử dụng hoạt động thông qua các màu từ trái sang phải theo đệ quy, theo các tuyên bố sau:

  • Bỏ qua tất cả các phần từ bên trái đã có màu yêu cầu. Việc đánh giá lại chúng một lần nữa sẽ không cung cấp câu trả lời tốt hơn.
  • Nếu thanh hoàn chỉnh đã có màu mong muốn, kết quả trả về 0 bước.
  • Mặt khác, lấy màu đích của phần ngoài cùng bên trái (tức là phần đầu tiên không có màu mong muốn).

    • Vẽ 1 phần với màu mục tiêu và lặp lại.
    • Sơn 2 phần với màu này và tái diễn.

    ...

    • Sơn toàn bộ thanh còn lại với màu này và tái diễn.

    Lấy tối thiểu của tất cả các số đó và thêm 1 (cho bước hiện tại). Trả lại đây là số bước tối ưu.

Thuật toán này hoạt động, bởi vì phần ngoài cùng bên trái phải được vẽ tại một thời điểm nào đó, vậy tại sao không thực hiện ngay lập tức - theo bất kỳ cách nào có thể.

.,n*         # prepare the initial situation (target stick, unpainted stick)
             # used n instead of '-' for the unpainted parts, because it is shorter
{            # Define the operator S which does t c S -> n
             #   - t: the desired target colors
             #   - c: the stick as it is colored currently
             #   - n: minimum number of steps required to go from c to t
  :c         # Assign the current configuration to the variable c
  ,,{[       # Map the list [0 1 2 .. L-1]
             # We will build a list of all possible configurations if we paint
             # the stick with the 0th part's color (either 1 or 2 or 3 or ... parts)
    ).       # Increase the number, i.e. we paint 1, 2, 3, ... L parts, copy
    2$1<     # Take the first color of the target configuration
    *        # ...paint as many parts
    \c>+     # ...and keep the rest as with the current stick
    1$       # take the target configuration
             # Top of stack now e.g. reads
             #    h----- hyghgy (for i=0)
             #    hh---- hyghgy (for i=1)
             # Next, we strip the common leading characters from both strings:
    .,,      # Make list [0 1 2 ... L-1]
    {        # Filter {}, all the numbers for which the first j+1 parts are the same
      ).     # incr j
      2$<    # take leftmost j parts of stick A
      \3$<   # take leftmost j parts of stick B
      =      # are they equal?
    },,      # The length of the result is the number of common parts.
    .@>      # cut parts from A
    @@>      # cut parts from B
  ]}%
  \;         # Remove the target from the stack (not needed anymore)               
             # We now have a list of possible paintings where 1, 2, ..., L parts were
             # painted from the left with the same color.
             # All configurations were reduced by the common parts (they won't be
             # painted over anyways)
  {~S)}%     # Call the method S recursively on the previously prepared configurations
  $0+0=      # $0= -> sort and take first, i.e. take the minimum, 0+ is a workaround
             # if the list was empty (i.e. the operator was called with a stick of length 0).
}:S
~            # Execute S

+1 cho thuật toán "sai màu ngoài cùng bên trái". Tuy nhiên, nó có vẻ là n!các bước;) (nhưng có lẽ đây là sự phức tạp thực sự, tôi không biết).
yo '

2

JavaScript: 187 byte

Giả sử chúng ta được phép chỉ có đầu vào và đầu ra cho một chức năng (xin vui lòng)!

function p(w){var j,l,s=-1,i,m=i=w.length;if(m<2)return m;for(;i--;){l = 1;for(var k=-1;(j=k)!=m;){if((k=w.indexOf(w[i],++j))==-1)k=m;l+=p(w.substring(j,k));}if(s==-1||l<s)s=l;}return s;}

157 Byte bằng cách thực hiện tối ưu hóa xấu hơn nữa (Đó là một phần của vấn đề và tôi thấy cực kỳ thú vị):

function p(w){var j,l,s=-1,i,m=i=w.length;if(m<2)return m;for(;i--;s<0|l<s?s=l:1)for(l=1,j=0;~j;)l+=p(w.substring(j,(j=w.indexOf(w[i],j))<0?m:j++));return s}

135 Byte Tôi nhận ra rằng độ dài của đầu vào là giới hạn trên và bây giờ tôi không cần phải xử lý các trường hợp tầm thường.

function p(w){var j,l,s,i,m=s=i=w.length;for(;i--;l<s?s=l:1)for(l=1,j=0;~j;)l+=p(w.substring(j,~(j=w.indexOf(w[i],j))?j++:m));return s}

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

p("YRYGR")
4
p("grG")
3
p("GyRyGyG")
4
p("pbgbrgrp")
5
p("hyghgy")
4

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

function paint(word) {
    var smallest = -1;
    if(word.length < 2) return word.length;
    for(var i = word.length; i-->0;) {
        var length = 1;
        for(var left, right = -1;(left = right) != m;) {
            if((right = word.indexOf(word[i],++left)) == -1) right = word.length;
            if(left != right) length += paint(word.substring(left , right));
        }
        if(smallest == -1 || length < smallest) smallest = l;
    }
    return smallest;
}

Đối với mỗi ký tự của đầu vào, hãy tính độ dài của mẫu nếu chúng ta tô màu đó trước. Điều này được thực hiện bằng cách giả vờ chúng ta vẽ màu đó và sau đó tạo các phần phụ ra khỏi các bit không phải là màu đó và gọi đệ quy phương thức sơn lên chúng. Con đường ngắn nhất được trả lại.

Ví dụ ( YRYGR):

Ban đầu, hãy thử R. Điều này cho chúng ta các nhóm phụ YYG. Yđược vẽ một cách tầm thường trong một lần.

YG: Hãy thử G, Ylà tầm thường, chiều dài 2. Hãy thử Y, Glà tầm thường, chiều dài 2. YGdo đó là chiều dài2 .

Vẽ tranh Rtrước tiên cho chúng ta1 + 1 + 2 = 4

Sau đó thử G. Điều này cho chúng ta các nhóm phụ YRYR. Rlà tầm thường.

Dành cho YRY:

Thử Y: Rlà tầm thường, chiều dài 2. Hãy thử R: YYlà hai nhóm, chiều dài 3.

YRY là chiều dài 2 .

Tranh Gđầu tiên cho1 + 1 + 2 = 4

Sau đó thử Y. Điều này cung cấp cho các nhóm phụ RGR. Rtầm thường, GRlà chiều dài 2. Ylà chiều dài4

Việc thực hiện này sau đó sẽ kiểm tra lại R và Y để giảm độ dài mã. Kết quả cho YRYGRlà do đó 4.


Tôi nghĩ rằng phiên bản mở rộng của bạn bị mất var mở đâu đó.
Hasturkun

Thật không may, phiên bản của bạn không đưa ra kết quả chính xác cho đầu vào "abcacba".
Howard

@Hasturkun mchỉ là viết tắt cho word.length:) @Howard Bạn đã đúng, tôi sẽ phải suy nghĩ lại về điều này.
meiamsome

1

Python, 149 ký tự

D=lambda s:0 if s=='?'*len(s)else min(1+D(s[:i]+'?'*(j-i)+s[j:])for i in range(len(s))for j in range(i+1,len(s)+1)if set(s[i:j])-set('?')==set(s[i]))

Tôi sử dụng ?để đánh dấu một khu vực có thể là bất kỳ màu nào. Dchọn một vùng liền kề của thanh chỉ chứa một màu duy nhất (cộng với có thể một số ?s), màu của vùng đó tồn tại, thay thế vùng đó bằng ?s và đệ quy để tìm tất cả các bước trước đó.

Thời gian chạy theo cấp số nhân. Chỉ cần đủ nhanh để làm các ví dụ trong một thời gian hợp lý (một vài phút). Tôi đặt cược với việc ghi nhớ nó có thể nhanh hơn nhiều.


1

Con trăn 3 - 122

def r(s,a):c=s[0];z=c in a;return s[1:]and min([1+r(s[1:],a+c)]+[r(s[1:],a[:a.rfind(c)+1])]*z)or(1-z)
print(r(input(),''))

Nó dường như hoạt động, nhưng tôi vẫn không chắc chắn 100% rằng phương pháp này sẽ luôn tìm thấy số bước tối thiểu.


1

CoffeeScript - 183 247 224 215 207

x=(s,c='')->return 0if !s[0]?;return x s[1..],c if s[0]is c;l=s.length;return x s[1...l],c if s[l-1]is c;i=s.lastIndexOf s[0];1+(x s[1...i],s[0])+x s[i+1..],c
y=(z)->z=z.split "";Math.min (x z),x z.reverse()

Bản trình diễn trên JSFiddle.net

Phiên bản chưa được chỉnh sửa bao gồm mã gỡ lỗi và nhận xét:

paintSubstring = (substring, color = '####') ->
  console.log 'Substring and color', substring, color, substring[0]
  # no need to color here
  if !substring[0]?
    return 0
  # no need to recolor the first part
  if substring[0] is color
    return paintSubstring (substring[1..]), color
  l = substring.length
  # no need to recolor the last part
  if substring[l-1] is color
    return paintSubstring substring[0...l], color
  # cover as much as possible
  index = substring.lastIndexOf substring[0]
  part1 = substring[1...index]
  part2 = substring[index+1..]
  console.log 'Part 1:', part1
  console.log 'Part 2:', part2
  # color the rest of the first half
  p1 = paintSubstring part1, substring[0]
  # color the rest of the second half, note that the color did not change!
  p2 = paintSubstring part2, color
  # sum up the cost of the substick + this color action
  return p1+p2+1
paintSubstringX=(x)->Math.min (paintSubstring x.split("")), paintSubstring x.split("").reverse()
console.clear()
input = """YRYGR
grG
GyRyGyG
pbgbrgrp
aaaaaaaa
hyghgy""".split /\n/
for stick in input
  console.log paintSubstringX stick

Xuất hiện để trả về một kết quả không chính xác cho hyghgy. Nó nói 5 nhưng phải là 4. (tuy nhiên, nó trả về kết quả đúng của 4 cho hyghgyh).
PhiNotPi

@PhiNotPi Chúa ơi, điều này đã đẩy tôi trở lại hơn 60 ký tự :( Cố gắng thực hiện lại điều này bằng ngôn ngữ khác, sau khi chợp mắt.
TimWolla

0

Haskell, 143 ký tự

f s=g(r n ' ')0where{r=replicate;n=length s;g p l=minimum$n:[0|p==s]++[1+g(take i p++r(j-i)(s!!i)++drop j p)(l+1)|l<n,i<-[0..n-1],j<-[i+1..n]]}

Điều này sẽ thử tất cả các cách viết có thể lên đến độ dài của chuỗi và cho đến khi nó tìm thấy một kiểu xây dựng mẫu đầu vào. Không cần phải nói, thời gian theo cấp số nhân (và sau đó một số).


0

Một tìm kiếm đầu tiên đơn giản. Nó không đặt bất cứ thứ gì vào hàng đợi đã được nhìn thấy. Nó hoạt động dưới một giây cho tất cả các ví dụ nhưng 'pbgbrgrp', thực sự mất trọn một phút :(

Bây giờ tôi có một cái gì đó hoạt động tôi sẽ làm việc để tìm kiếm một cái gì đó nhanh hơn và ngắn hơn.

Con trăn - 300 296

def f(c):
 k=len(c);q=['0'*99];m={};m[q[0]]=1
 while q:
  u=q.pop(0)
  for x in ['0'*j+h*i+'0'*(k-j-i) for h in set(c) for j in range(1+k) for i in range(1,1+k-j)]:
   n=''.join([r if r!='0' else l for l,r in zip(u,x)])
   if n == c:
     return m[u]
   if not n in m:
    m[n]=m[u]+1;q.append(n)

Bạn có thể vui lòng kiểm tra vết lõm? Nó dường như bị phá vỡ.
Howard

@Howard cố định. Tôi không biết tôi đã nghĩ gì tối qua.
TrevorM

0

Haskell, 118 86 ký tự

p""=0
p(a:s)=1+minimum(map(sum.map p.words)$sequence$map(a%)s)
a%b|a==b=b:" "|1<3=[b]

Chạy thử:

λ: p "YRYGR"
4

λ: p "grG"
3

λ: p "GyRyGyG"
4

λ: p "pbgbrgrp"
5

λ: p "hyghgy"
4

λ: p "abcacba"
4

Phương pháp này thậm chí không hiệu quả!

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.