ใช้เวลาในการทาสีนานแค่ไหน?


12

(ขึ้นอยู่กับปัญหา Math.SE นี้ซึ่งให้กราฟิกบางส่วน)

ฉันมีไม้เท้าซึ่งดูเหมือนจะเป็นแบบนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันอยากให้มันดูเป็นแบบนี้:

ป้อนคำอธิบายรูปภาพที่นี่

อย่างไรก็ตามฉันไม่ได้เป็นจิตรกรผู้เชี่ยวชาญดังนั้นก่อนที่ฉันจะเริ่มโครงการ DIY ที่ทะเยอทะยานฉันต้องการให้แน่ใจว่าฉันไม่ได้อยู่ในหัวของฉัน

โปรแกรมของคุณควรบอกฉันว่ามีกี่ขั้นตอนในการทาสีแท่งนี้ แต่ละขั้นตอนเกี่ยวข้องกับการวาดภาพพื้นที่ต่อเนื่องด้วยสีทึบซึ่งครอบคลุมชั้นของสีก่อนหน้า สำหรับตัวอย่างข้างต้นฉันสามารถวาดครึ่งซ้ายสีน้ำเงินครึ่งขวาสีแดงจากนั้นพื้นที่สีเขียวสองแห่งแยกเป็น 4 ขั้นตอนทั้งหมด (สีเขียวไม่ได้ทาสีอย่างต่อเนื่อง)

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือใน ASCII:

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

มีสองวิธีที่แตกต่างกันในการทาสีคันนี้และจบลงด้วยผลลัพธ์เดียวกัน ฉันสนใจในการประมาณเวลาเท่านั้นซึ่งเป็นสี่ขั้นตอน

เป้าหมาย

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

อินพุต

โปรแกรมของคุณจะได้รับชุดสีสำหรับแท่งในรูปแบบของตัวอักษร แต่ละตัวอักษรที่ไม่ซ้ำกัน (กรณีที่สำคัญ) หมายถึงสีที่ไม่ซ้ำกัน

YRYGR

grG

GyRyGyG

pbgbrgrp

hyghgy

เอาท์พุต

ตัวเลขเหล่านี้เป็นขั้นตอนจำนวนน้อยที่สุดที่จำเป็นในการทาสีแท่ง

4

3

4

5

4

คำอธิบาย

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

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

 ---
 g--
 gr-
 grG

 -------
 GGGGGGG
 GyyyGGG
 GyRyGGG
 GyRyGyG

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

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

แก้ไข: ฉันจะเพิ่มกรณีทดสอบเพิ่มเติมหากพิสูจน์ได้ว่าเป็นกรณีทดสอบที่ยากขึ้น


สิ่งนี้ทำให้ฉันนึกถึงstackoverflow.com/q/10364248/785745ซึ่งคล้ายกัน แต่ใน 2D
Kendall Frey

คำตอบ:


3

GolfScript, 82 72 67 ตัวอักษร

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

เร็วพอสมควรสำหรับโปรแกรม GolfScript ตัวอย่าง:

> hyghgy
4

> pbgbrgrp
5

อัลกอริทึมที่ใช้ทำงานผ่านสีจากซ้ายไปขวาแบบเรียกซ้ำตามข้อความต่อไปนี้:

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

    • วาดส่วนที่ 1 ด้วยสีเป้าหมายและเรียกคืน
    • สี 2 ส่วนด้วยสีนี้และเรียกคืน

    ...

    • ทาสีคันที่เหลือทั้งหมดด้วยสีนี้และเรียกคืน

    ใช้จำนวนขั้นต่ำทั้งหมดและเพิ่ม 1 (สำหรับขั้นตอนปัจจุบัน) ส่งคืนสิ่งนี้เป็นจำนวนขั้นตอนที่เหมาะสมที่สุด

อัลกอริทึมนี้ใช้งานได้เนื่องจากส่วนด้านซ้ายสุดจะต้องมีการทาสีในครั้งเดียวดังนั้นทำไมไม่ทำทันที - ในแบบที่เป็นไปได้

.,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 สำหรับอัลกอริทึม "สีซ้ายสุดผิด" อย่างไรก็ตามดูเหมือนว่าจะเป็นn!ขั้นตอน;) (แต่นี่อาจจะเป็นความซับซ้อนที่แท้จริงฉันไม่รู้)
yo '

2

จาวาสคริปต์: 187ไบต์

สมมติว่าเราได้รับอนุญาตให้มีเพียงอินพุตและเอาต์พุตไปยังฟังก์ชัน (โปรด)!

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 Bytesด้วยการเพิ่มประสิทธิภาพที่น่าเกลียด (ซึ่งเป็นส่วนหนึ่งของจุดและฉันพบว่าสนุกอย่างเหลือเชื่อ):

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 Bytesฉันรู้ว่าความยาวของอินพุตเป็นขอบเขตบนและตอนนี้ฉันไม่จำเป็นต้องจัดการกับเรื่องเล็ก ๆ น้อย ๆ แยกกันในตอนนี้

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}

กรณีทดสอบ:

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

รุ่นที่ขยาย:

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

สำหรับอักขระทุกตัวของอินพุตให้คำนวณความยาวของลวดลายถ้าเราวาดสีนั้นก่อน สิ่งนี้ทำได้โดยทำท่าว่าเราจะทาสีสีนั้นแล้วตัดส่วนย่อยออกจากบิตที่ไม่ใช่สีนั้นและเรียกวิธีการทาสีซ้ำ ๆ เส้นทางที่สั้นที่สุดจะถูกส่งกลับ

ตัวอย่าง ( YRYGR):

Rในขั้นต้นลอง นี้ทำให้เรามีกลุ่มย่อยและY ถูกทาสีเล็กน้อยในครั้งเดียวYGY

สำหรับYG: ลองG, ไม่ได้เป็นเรื่องยาวY 2ลองY, Gน่ารำคาญ, ความยาว 2 ดังนั้นจึงเป็นเรื่องยาวYG2

จิตรกรรมRก่อนจึงให้เรา1 + 1 + 2 = 4

Gแล้วลอง นี้ทำให้เรามีกลุ่มย่อยและYRY ไม่สำคัญRR

สำหรับYRY:

ลองY: ไม่ได้เป็นเรื่องยาวR 2ลองR: Yและเป็นสองกลุ่มมีความยาวY3

YRY2คือความยาว

จิตรกรรมGครั้งแรกให้1 + 1 + 2 = 4

Yแล้วลอง นี้จะช่วยให้กลุ่มย่อยและR จิ๊บจ๊อยคือความยาว คือความยาวGRRGR2Y4

การใช้งานนี้จะตรวจสอบ R และ Y อีกครั้งเพื่อลดความยาวรหัส ผลการดำเนินงานจึงเป็นYRYGR4


ผมคิดว่ารุ่นที่ขยายตัวของคุณหายไปวาmที่ไหนสักแห่ง
Hasturkun

"abcacba"แต่น่าเสียดายที่ยังมีรุ่นของคุณไม่ได้ให้ผลที่ถูกต้องสำหรับการป้อนข้อมูล
Howard

@Hasturkun mแค่จดชวเลขword.length:) @Howard คุณถูกต้องฉันจะต้องคิดใหม่อีกครั้ง
meiamsome

1

Python 149 ตัวอักษร

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]))

ฉันใช้?เพื่อทำเครื่องหมายบริเวณที่อาจมีสีใด ๆ Dเลือกพื้นที่ที่ต่อเนื่องกันของแท่งที่มีเพียงสีเดียว (รวมถึงบางส่วน?) สีที่ภูมิภาคสุดท้ายแทนที่พื้นที่นั้นด้วย?s และ recurses เพื่อหาขั้นตอนก่อนหน้าทั้งหมด

เวลาทำงานแบบเอ็กซ์โปเนนเชียล เร็วพอที่จะทำตัวอย่างในเวลาที่เหมาะสม (ไม่กี่นาที) ฉันเดิมพันด้วยการบันทึกความจำมันอาจจะเร็วกว่ามาก


1

Python 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(),''))

ดูเหมือนว่าจะใช้งานได้ แต่ฉันก็ยังไม่แน่ใจ 100% ว่าวิธีนี้จะหาจำนวนขั้นต่ำเสมอ


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()

ตัวอย่างบน JSFiddle.net

รุ่นที่ไม่ได้บรรจุรวมถึงรหัสการซ่อมแซม

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

hyghgyดูเหมือนจะกลับมาผลที่ไม่ถูกต้องสำหรับ มันบอกว่า 5 แต่ควรเป็น 4 (อย่างไรก็ตามมันจะคืนค่าผลลัพธ์ที่ถูกต้องของ 4 สำหรับhyghgyh)
PhiNotPi

@PhiNotPi พระเจ้านี่ทำให้ฉันกลับมาเป็นตัวละครเกิน 60 ตัว :( พยายามใช้ภาษานี้เป็นภาษาอื่นอีกครั้งหลังจากหลับนอน
TimWolla

0

Haskell, 143 chars

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

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


0

การค้นหาความกว้างอย่างง่ายครั้งแรก ไม่ได้ใส่อะไรลงไปในคิวที่ได้เห็นไปแล้ว มันใช้งานได้ภายในไม่กี่วินาทีสำหรับตัวอย่างทั้งหมด แต่ 'pbgbrgrp' ซึ่งใช้เวลาเต็มหนึ่งนาที :(

ตอนนี้ฉันมีบางอย่างที่ใช้งานได้ฉันจะพยายามค้นหาบางสิ่งให้เร็วขึ้นและสั้นลง

Python - 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)

คุณช่วยตรวจสอบการเยื้องได้ไหม ดูเหมือนว่าจะถูกทำลาย
Howard

@ แก้ไขไปแล้ว ฉันไม่รู้ว่าฉันคิดอะไรเมื่อคืนนี้
TrevorM

0

Haskell, 118 86 ตัวอักษร

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

ทดสอบการทำงาน:

λ: p "YRYGR"
4

λ: p "grG"
3

λ: p "GyRyGyG"
4

λ: p "pbgbrgrp"
5

λ: p "hyghgy"
4

λ: p "abcacba"
4

วิธีนี้ไม่ได้มีประสิทธิภาพแม้แต่น้อยทั้งหมด!

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