ค้นหาหมายเลขรงค์


13

น่าแปลกที่เรายังไม่มีความท้าทายในการระบายสีกราฟ!

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

ตัวอย่างเช่นต่อไปนี้แสดงสีที่ถูกต้องโดยใช้จำนวนสีขั้นต่ำ:

(พบใน Wikipedia)

ดังนั้นจำนวนสีของกราฟนี้เป็นχ = 3

เขียนโปรแกรมหรือฟังก์ชั่นที่กำหนดจำนวนจุดยอดN <16 (ซึ่งมีหมายเลขจาก1ถึงN ) และรายการของขอบกำหนดจำนวนสีของกราฟ

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

คุณไม่สามารถใช้ฟังก์ชั่นที่เกี่ยวข้องกับทฤษฎีกราฟในตัว (เช่น Mathematica ChromaticNumber)

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

นี่คือรหัสกอล์ฟคำตอบที่สั้นที่สุด (เป็นไบต์) ชนะ

ตัวอย่าง

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

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

สามเหลี่ยม (χ = 3)

3
1 2, 2 3, 1 3

"วงแหวน" ของ 6 จุดยอด (χ = 2)

6
1 2, 2 3, 3 4, 4 5, 5 6, 6 1

"วงแหวน" ของ 5 จุดยอด (χ = 3)

5
1 2, 2 3, 3 4, 4 5, 5 1

ภาพตัวอย่างด้านบน (χ = 3)

6
1 2, 2 3, 3 4, 4 5, 5 6, 6 1, 1 3, 2 4, 3 5, 4 6, 5 1, 6 2

ลักษณะทั่วไปของด้านบนสำหรับ 7 จุดยอด (χ = 4)

7
1 2, 2 3, 3 4, 4 5, 5 6, 6 7, 7 1, 1 3, 2 4, 3 5, 4 6, 5 7, 6 1, 7 2

กราฟ Petersen (χ = 3)

10
1 2, 2 3, 3 4, 4 5, 5 1, 1 6, 2 7, 3 8, 4 9, 5 10, 6 8, 7 9, 8 10, 9 6, 10 7

กราฟที่สมบูรณ์ของ 5 จุดยอดรวมถึงจุดยอดที่ตัดการเชื่อมต่อ (χ = 5)

6
1 2, 1 3, 1 4, 1 5, 2 3, 2 4, 2 5, 3 4, 3 5, 4 5

กราฟสมบูรณ์ของ 8 จุดยอด (χ = 8)

8
1 2, 1 3, 1 4, 1 5, 1 6, 1 7, 1 8, 2 3, 2 4, 2 5, 2 6, 2 7, 2 8, 3 4, 3 5, 3 6, 3 7, 3 8, 4 5, 4 6, 4 7, 4 8, 5 6, 5 7, 5 8, 6 7, 6 8, 7 8

ตาข่ายรูปสามเหลี่ยม 15 จุด (ices = 3)

15
1 2, 1 3, 2 3, 2 4, 2 5, 3 5, 3 6, 4 5, 5 6, 4 7, 4 8, 5 8, 5 9, 6 9, 6 10, 7 8, 8 9, 9 10, 7 11, 7 12, 8 12, 8 13, 9 13, 9 14, 10 14, 10 15, 11 12, 12 13, 13 14, 14 15

คุณสามารถกำหนดเหตุผลได้ไหม 1 นาที? 10?
ThreeFx

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

คำตอบ:


4

Python 2.7 - 122 109 111 109 108 103

f=lambda n,e,m=1:any(all(t*m//m**a%m!=t*m//m**b%m for(a,b)in e)for t in range(m**n))and m or f(n,e,m+1)

การใช้งาน:

print f(5, [(1, 2), (2, 3), (3, 4), (4, 5), (5, 1)])

กำลังดุร้ายด้วยการเพิ่มจำนวนสี (m) และตรวจสอบสีที่เป็นไปได้ทั้งหมด หนึ่งสีสามารถอธิบายได้ว่าเป็นตัวเลขในฐาน m ดังนั้นสีที่เป็นไปได้คือ 0, 1, ... , m ^ n-1

แก้ไข: กราฟที่สมบูรณ์ของ 8 จุดยอดใช้เวลาค่อนข้างนาน แต่แล็ปท็อปของฉันสามารถแก้ไขได้ในเวลาประมาณ 10 นาที อีกกรณีทดสอบใช้เวลาเพียงไม่กี่วินาที


แก้ไข 2: อ่านว่าการประมวลผลล่วงหน้าได้รับอนุญาตดังนั้นฉันปล่อยให้ดัชนีของจุดยอดเริ่มต้นด้วย 0: ย่อ t * m // m ** x% m เป็น t // m ** a% m (-2) ละลายแลมบ์ดาแล้วใส่ m เข้าไปในฟังก์ชัน params (-11)


แก้ไข 3: ไม่อนุญาตการประมวลผลล่วงหน้า-> กลับสู่ t * m (+4), // ไปที่ / (-2) อย่างง่าย


แก้ไข 4: ลบวงเล็บเหลี่ยมในใด ๆ (-2) ขอบคุณ xnor


แก้ไข 5: แทนที่จะใช้โมดูโล m สองครั้งเพียงแค่ลบออกแล้วใช้โมดูโล (-1) นี่ก็เป็นการปรับปรุงประสิทธิภาพ การทดสอบทั้งหมดเข้าด้วยกันใช้เวลาประมาณ 25 วินาทีบนแล็ปท็อปของฉัน


แก้ไข 6: การโทรซ้ำซ้ำขณะที่ 1: และ m + = 1 (-5) ขอบคุณอีกครั้ง xnor


วิธีการที่ดี สนามกอล์ฟที่เรียบง่าย: คุณสามารถลบวงเล็บในall([...])ถ้าคุณใส่a,bใน parens (ซึ่งไม่มีค่าใช้จ่ายใด ๆ ที่นี่เนื่องจากการเว้นวรรค) เพื่อallไม่ให้เกิดข้อผิดพลาดสำหรับอาร์กิวเมนต์เพิ่มเติม นอกจากนี้ฉันสงสัยว่าคุณสามารถบันทึกตัวอักษรถ้าคุณเรียกคืนด้วยการเรียกใช้ฟังก์ชันไปยังจุดสูงสุดถัดไปmแทนที่จะใช้ลูป while
xnor

ขอบคุณวิธีการแบบเรียกซ้ำใช้เวลา 2 ตัวอักษร A สำหรับ m ในช่วง (n + 1)
Jakube

ฉันปรับวิธีการแบบวนซ้ำด้วยวิธีanyและand/orเคล็ดลับแล้วก็บันทึกตัวอักษรบางตัว: f=lambda n,e,m=1:any(all(t*m//m**a%m!=t*m//m**b%m for(a,b)in e)for t in range(m**n))and m or f(n,e,m+1).
xnor

2

Java - 241 218

int k,j,c;int f(int n,int[]e){for(k=1;k<=n;k++)for(long p=0;p<x(n);p++){for(j=0,c=0;j<e.length;c=p%x(e[j])/x(e[j]-1)==p%x(e[j+1])/x(e[j+1]-1)?1:c,j+=2);if(c<1)return k;}return 0;}int x(int a){return(int)Math.pow(k,a);}

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

สิ่งนี้ใช้เวลานานที่สุดสำหรับกรณีทดสอบสำหรับχ = 8(กราฟเต็มดูดที่นี่) แต่ก็ยังคงอยู่ภายใต้ 15 วินาที (ตกลงประมาณ 100 วินาทีพร้อมการแก้ไขล่าสุด)

อินพุตคือจำนวนของจุดยอดnและอาร์เรย์ของจุดยอดขอบที่e[]กำหนดในลำดับเดียวกับค่าที่คั่นด้วยเครื่องหมายจุลภาคของ OPs

ด้วยตัวแบ่งบรรทัด:

int k,j,c;
int f(int n,int[]e){
    for(k=1;k<=n;k++)
        for(long p=0;p<x(n);p++){
            for(j=0,c=0;
                j<e.length;
                c=p%x(e[j])/x(e[j]-1)==p%x(e[j+1])/x(e[j+1]-1)?1:c,
                j+=2);
            if(c<1)return k;
        }
    return 0;
}
int x(int a){return(int)Math.pow(k,a);}

โอ้และสิ่งนี้ถือว่าอินพุตเป็นกราฟที่มีสีสัน หากขอบลูปจาก v1 ถึง v1 หรือไม่มีจุดยอดก็ไม่สามารถทำสีได้และจะส่งออก 0 มันจะยังคงใช้งานได้กับกราฟที่ไม่มีขอบχ=1ฯลฯ


2

Python 3 - 162

ใช้วิธีการบังคับแบบเดรัจฉานเหมือนกัน แต่ใช้ไลบรารี itertools เพื่อสร้างชุดค่าผสมที่เร็วขึ้นหวังว่า แก้ปัญหา 8-graph สมบูรณ์ใน <1 นาทีบนเครื่องธรรมดาของฉัน

import itertools as I
def c(n,v):
 for i in range(1,n+1):
  for p in I.product(range(i),repeat=n):
   if(0==len([x for x in v if(p[x[0]]==p[x[1]])])):return i

ตัวอย่างการใช้งานสำหรับกรณีกราฟ 8 ตัว:

print(c(8,[x for x in I.combinations(range(8), 2)]))

1

Haskell, 163 ไบต์

p x=f(length x)(transpose x)1
f a[b,c]d|or$map(\x->and$g x(h b)(h c))(sequence$replicate a[1..d])=d|0<1=f a b c(d+1)
g a=zipWith(\x y->a!!x/=a!!y)
h=map(flip(-)1)

การใช้งานจะเป็นเช่นนี้:

p [[1, 2],[2, 3],[3, 1]]

วิธีการพื้นฐานของกำลังดุร้าย ตรวจสอบการผสมสีที่เป็นไปได้ทั้งหมดว่าถูกต้องหรือไม่ ไม่มากที่จะพูดที่นี่ยกเว้นว่าฉันยินดีที่จะได้ยินเคล็ดลับใด ๆ สำหรับการทำให้สั้นลงอีก;)


ฉันจะบอกว่าการลดลงของจุดยอดและ transposing พวกเขานับเป็น "preprocessing" สิ่งที่ฉันมีในใจกับ "รูปแบบที่สะดวกใด ๆ " ค่อนข้างที่คุณสามารถเลือกจากรายการแบบเรียบ, รายการซ้อน, สตริง, สตริงที่มีตัวคั่นสะดวก ฯลฯ ... แต่โครงสร้างที่แบนควรจะเหมือนกับที่ระบุไว้ในความท้าทาย
Martin Ender

@ MartinBüttnerเอาล่ะฉันจะเปลี่ยนมัน
ThreeFx

@ThreeFx all idเป็นเช่นเดียวกับand, any idเป็นเช่นเดียวกับorและเป็นเช่นเดียวกับเพียงany id$map f list any f listนอกจากนี้คุณสามารถทำบางสิ่งด้วยg: คุณสามารถกำหนดใหม่เป็นg a=(and.).zipWith(\x y->a!!x/=a!!y)ทำให้มัดเปลี่ยนลำดับการป้อนข้อมูลเพื่อแทนที่(\x->g x b c)ด้วยg b cหรือแม้กระทั่งทำให้มันปราศจากจุดและอินไลน์ บางส่วนของสิ่งเหล่านี้ไม่ได้ทำงานร่วมกันดังนั้นลองพวกเขาทั้งหมดและเลือกหนึ่งที่ดีที่สุด :)
ภูมิใจ haskeller

1
@ MartinBüttnerฉันคิดว่ามันคงที่กับค่าของ maaaaany bytes : D
ThreeFx

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