แก้ปัญหาแปดราชินีในเวลาคอมไพล์ [ปิด]


39

คุณสามารถไขปริศนาแปดราชินีในเวลารวบรวมได้หรือไม่?

เลือกรูปแบบผลลัพธ์ที่เหมาะสม

ฉันสนใจเป็นพิเศษในการแก้ปัญหาการเขียนโปรแกรมเทมเพลต metaprogramming ของ C ++ แต่คุณสามารถใช้ภาษาที่มีโครงสร้างคล้ายกันเช่นระบบประเภทของ Haskell

หลักการที่ดีเมตาโปรแกรมของคุณจะแสดงผลโซลูชันทั้งหมด ไม่มีการเข้ารหัส


ทำไมคุณไม่อนุญาตให้ใช้ภาษาต่าง ๆ
ผู้ใช้ที่ไม่รู้จัก

@user: เพราะฉันสนใจ C ++ TMP solution หากคุณรู้จักภาษาที่มีโครงสร้างคล้ายกันมากคุณสามารถโพสต์คำตอบได้ฟรี
R. Martinho Fernandes

ฉันสามารถใช้ระบบประเภทของ Haskell ได้หรือไม่ AFAIK มันควรจะสมบูรณ์แบบ
FUZxxl

@FUZxxl: ใช่ ฉันจะแก้ไขคำถาม
R. Martinho Fernandes

มันเพียงพอแล้วหรือยังที่จะทำแบบ brute-force-solution?
หยุดที่จะเปลี่ยนรหัสลับเมื่อ

คำตอบ:


50

เมตาโปรแกรมของฉันค้นหาโซลูชันทั้งหมด 92 รายการ พวกเขาจะพิมพ์เป็นข้อความผิดพลาด:

error: 'solution' is not a member of 'print<15863724>'

นี่หมายความว่าควรวางราชินีคนแรกที่ y = 1, ที่สองที่ y = 5, ที่สามที่ y = 8 เป็นต้นไป

ก่อนอื่นฟังก์ชันเมตาที่มีประโยชน์บางประการ:

template <typename T>
struct return_
{
    typedef T type;
};

template <bool Condition, typename Then, typename Else>
struct if_then_else;

template <typename Then, typename Else>
struct if_then_else<true, Then, Else> : return_<Then> {};

template <typename Then, typename Else>
struct if_then_else<false, Then, Else> : return_<Else> {};

template <int N>
struct constant
{
    enum { value = N };
};

template <int N>
struct print
{
    // empty body -> member access yields a compiler error involving N
};

จากนั้นฟังก์ชันเมตาสองฟังก์ชันที่น่าสนใจ (สังเกตเอกพจน์และพหูพจน์):

template <int queens, int rows, int sums, int difs, int x, int y>
struct put_queen;

template <int queens, int rows, int sums, int difs, int x>
struct put_queens : constant
     < put_queen<queens, rows, sums, difs, x, 1>::value
     + put_queen<queens, rows, sums, difs, x, 2>::value
     + put_queen<queens, rows, sums, difs, x, 3>::value
     + put_queen<queens, rows, sums, difs, x, 4>::value
     + put_queen<queens, rows, sums, difs, x, 5>::value
     + put_queen<queens, rows, sums, difs, x, 6>::value
     + put_queen<queens, rows, sums, difs, x, 7>::value
     + put_queen<queens, rows, sums, difs, x, 8>::value > {};

template <int queens, int rows, int sums, int difs, int x, int y>
struct put_queen : if_then_else<
    rows & (1 << y) || sums & (1 << (x + y)) || difs & (1 << (8 + x - y)),
    constant<0>,
    put_queens<queens * 10 + y, rows | (1 << y), sums | (1 << (x + y)),
               difs | (1 << (8 + x - y)), x + 1>
>::type {};

ตัวแปรจะqueensเก็บพิกัด y ของราชินีที่วางไว้บนกระดาน ตัวแปรสามตัวต่อไปนี้จัดเก็บแถวและเส้นทแยงมุมที่ถูกครอบครองโดยราชินี xและyควรอธิบายด้วยตนเอง

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

เมื่อ x ถึง 8 เราพบวิธีแก้ไข:

template <int queens, int rows, int sums, int difs>
struct put_queens<queens, rows, sums, difs, 8>
{
    enum { value = print<queens>::solution };
};

เนื่องจากprintเทมเพลตไม่มีสมาชิกsolutionคอมไพเลอร์จะสร้างข้อผิดพลาด

และสุดท้ายเพื่อเริ่มกระบวนการเราตรวจสอบvalueสมาชิกของกระดานว่าง:

int go = put_queens<0, 0, 0, 0, 0>::value;

โปรแกรมที่สมบูรณ์สามารถพบได้ที่ideone


2
ฉันชอบ: 1) การใช้ bitfields ในการจัดเก็บข้อมูล 2) ทางเลือกของวิธีการส่งออก
R. Martinho Fernandes

7
คำตอบเดียวเกินคำบรรยาย
st0le

มันควรจะไม่ส่งออกค่า x หรือไม่?
DeadMG

2
@DeadMG ค่า x ของตำแหน่ง Queen แต่ละตำแหน่งคือตำแหน่งในสตริง (1-8)
Briguy37

22

ฉันคิดวิธีแก้ปัญหาที่ใช้ระบบประเภท Haskell ฉันใช้วิธีแก้ปัญหาที่มีอยู่ในระดับค่าเปลี่ยนไปเล็กน้อยจากนั้นยกระดับเป็นระดับประเภท ต้องใช้การคิดค้นใหม่จำนวนมาก ฉันต้องเปิดใช้งานส่วนขยาย GHC มากมาย

ครั้งแรกเนื่องจากจำนวนเต็มไม่ได้รับอนุญาตในระดับประเภทฉันต้องบูรณาการจำนวนธรรมชาติอีกครั้งคราวนี้เป็นประเภท:

data Zero -- type that represents zero
data S n  -- type constructor that constructs the successor of another natural number
-- Some numbers shortcuts
type One = S Zero
type Two = S One
type Three = S Two
type Four = S Three
type Five = S Four
type Six = S Five
type Seven = S Six
type Eight = S Seven

อัลกอริทึมที่ฉันดัดแปลงทำให้การบวกและลบบนธรรมชาติดังนั้นฉันต้องบูรณาการสิ่งเหล่านี้เช่นกัน ฟังก์ชั่นที่ระดับประเภทถูกกำหนดด้วยรีสอร์ตเพื่อพิมพ์คลาส สิ่งนี้ต้องการส่วนขยายสำหรับคลาสชนิดพารามิเตอร์หลายตัวและการพึ่งพาการทำงาน คลาสประเภทไม่สามารถ "คืนค่า" ดังนั้นเราจึงใช้พารามิเตอร์พิเศษสำหรับสิ่งนั้นในลักษณะที่คล้ายกับ PROLOG

class Add a b r | a b -> r -- last param is the result
instance Add Zero b b                     -- 0 + b = b
instance (Add a b r) => Add (S a) b (S r) -- S(a) + b = S(a + b)

class Sub a b r | a b -> r
instance Sub a Zero a                     -- a - 0 = a
instance (Sub a b r) => Sub (S a) (S b) r -- S(a) - S(b) = a - b

การเรียกซ้ำถูกนำไปใช้กับการยืนยันคลาสดังนั้นไวยากรณ์จะมีลักษณะย้อนหลังเล็กน้อย

ถัดไปเป็นบูลีน:

data True  -- type that represents truth
data False -- type that represents falsehood

และฟังก์ชั่นในการทำการเปรียบเทียบความไม่เท่าเทียมกัน:

class NotEq a b r | a b -> r
instance NotEq Zero Zero False                -- 0 /= 0 = False
instance NotEq (S a) Zero True                -- S(a) /= 0 = True
instance NotEq Zero (S a) True                -- 0 /= S(a) = True
instance (NotEq a b r) => NotEq (S a) (S b) r -- S(a) /= S(b) = a /= b

และรายการ ...

data Nil
data h ::: t
infixr 0 :::

class Append xs ys r | xs ys -> r
instance Append Nil ys ys                                       -- [] ++ _ = []
instance (Append xs ys rec) => Append (x ::: xs) ys (x ::: rec) -- (x:xs) ++ ys = x:(xs ++ ys)

class Concat xs r | xs -> r
instance Concat Nil Nil                                         -- concat [] = []
instance (Concat xs rec, Append x rec r) => Concat (x ::: xs) r -- concat (x:xs) = x ++ concat xs

class And l r | l -> r
instance And Nil True                    -- and [] = True
instance And (False ::: t) False         -- and (False:_) = False
instance (And t r) => And (True ::: t) r -- and (True:t) = and t

ifs หายไปที่ระดับประเภท ...

class Cond c t e r | c t e -> r
instance Cond True t e t  -- cond True t _ = t
instance Cond False t e e -- cond False _ e = e

และด้วยสิ่งนั้นเครื่องจักรสนับสนุนทั้งหมดที่ฉันใช้อยู่ก็เข้ามาแทนที่ ถึงเวลาจัดการปัญหาเอง!

เริ่มต้นด้วยฟังก์ชั่นเพื่อทดสอบว่าการเพิ่มราชินีเข้ากับบอร์ดที่มีอยู่นั้นใช้ได้หรือไม่:

-- Testing if it's safe to add a queen
class Safe x b n r | x b n -> r
instance Safe x Nil n True    -- safe x [] n = True
instance (Safe x y (S n) rec,
          Add c n cpn, Sub c n cmn,
          NotEq x c c1, NotEq x cpn c2, NotEq x cmn c3,
          And (c1 ::: c2 ::: c3 ::: rec ::: Nil) r) => Safe x (c ::: y) n r
    -- safe x (c:y) n = and [ x /= c , x /= c + n , x /= c - n , safe x y (n+1)]

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

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

queens 0 = [[]]
-- The original used the list monad. I "unrolled" bind into concat & map.
queens n = concat $ map f $ queens (n-1)
g y x = if safe x y 1 then [x:y] else []
f y = concat $ map (g y) [1..8]

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

-- Auxiliary meta-functions
class G y x r | y x -> r
instance (Safe x y One s, Cond s ((x ::: y) ::: Nil) Nil r) => G y x r

class MapG y l r | y l -> r
instance MapG y Nil Nil
instance (MapG y xs rec, G y x g) => MapG y (x ::: xs) (g ::: rec)

-- Shortcut for [1..8]
type OneToEight = One ::: Two ::: Three ::: Four ::: Five ::: Six ::: Seven ::: Eight ::: Nil

class F y r | y -> r
instance (MapG y OneToEight m, Concat m r) => F y r -- f y = concat $ map (g y) [1..8]

class MapF l r | l -> r
instance MapF Nil Nil
instance (MapF xs rec, F x f) => MapF (x ::: xs) (f ::: rec)

และเมตาฟังก์ชั่นสุดท้ายสามารถเขียนได้ตอนนี้:

class Queens n r | n -> r
instance Queens Zero (Nil ::: Nil)
instance (Queens n rec, MapF rec m, Concat m r) => Queens (S n) r

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

-- dummy value of type Eight
eight = undefined :: Eight
-- dummy function that asserts the Queens class
queens :: Queens n r => n -> r
queens = const undefined

เมตาโปรแกรมนี้ควรจะทำงานกับตัวตรวจสอบชนิดเพื่อให้สามารถเริ่มทำงานghciและขอประเภทของqueens eight:

> :t queens eight

สิ่งนี้จะเกินขีด จำกัด การเรียกซ้ำที่เป็นค่าเริ่มต้นค่อนข้างเร็ว (เป็น 20 อัน) เพื่อเพิ่มขีด จำกัด นี้เราจำเป็นต้องเรียกใช้ghciกับ-fcontext-stack=Nตัวเลือกที่Nเป็นที่ต้องการความลึกสแต็ค (N = 1000 และสิบห้านาทีไม่เพียงพอ) ฉันไม่ได้เห็นการทำงานนี้จะเสร็จสิ้นยังเป็นมันใช้เวลานานมาก queens fourแต่ฉันจัดการเพื่อวิ่งขึ้นไป

มีโปรแกรมเต็มรูปแบบบน ideone กับเครื่องจักรบางอย่างสำหรับการพิมพ์ประเภทผลลัพธ์ที่สวยงาม แต่queens twoสามารถทำงานได้โดยไม่เกินขีด จำกัด :(


นอกจากวิธีแก้ปัญหาที่น่าสนใจนี่คือการอ้างอิงที่สนุกกับสิ่งที่สามารถทำได้ด้วยตรรกะคลาส / อินสแตนซ์
Michael Klein

11

C ผ่านตัวประมวลผลล่วงหน้า

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

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

#ifdef i
# if (r_(i) & 1 << j_(i)) == 0 && (p_(i) & 1 << i + j_(i)) == 0 \
                               && (n_(i) & 1 << 7 + i - j_(i)) == 0
#  if i == 0
#   undef i
#   define i 1
#   undef r1
#   undef p1
#   undef n1
#   define r1 (r0 | (1 << j0))
#   define p1 (p0 | (1 << j0))
#   define n1 (n0 | (1 << 7 - j0))
#   undef j1
#   define j1 0
#   include __FILE__
#   undef j1
#   define j1 1
#   include __FILE__
#   undef j1
#   define j1 2
#   include __FILE__
#   undef j1
#   define j1 3
#   include __FILE__
#   undef j1
#   define j1 4
#   include __FILE__
#   undef j1
#   define j1 5
#   include __FILE__
#   undef j1
#   define j1 6
#   include __FILE__
#   undef j1
#   define j1 7
#   include __FILE__
#   undef i
#   define i 0
#  elif i == 1
#   undef i
#   define i 2
#   undef r2
#   undef p2
#   undef n2
#   define r2 (r1 | (1 << j1))
#   define p2 (p1 | (1 << 1 + j1))
#   define n2 (n1 | (1 << 8 - j1))
#   undef j2
#   define j2 0
#   include __FILE__
#   undef j2
#   define j2 1
#   include __FILE__
#   undef j2
#   define j2 2
#   include __FILE__
#   undef j2
#   define j2 3
#   include __FILE__
#   undef j2
#   define j2 4
#   include __FILE__
#   undef j2
#   define j2 5
#   include __FILE__
#   undef j2
#   define j2 6
#   include __FILE__
#   undef j2
#   define j2 7
#   include __FILE__
#   undef i
#   define i 1
#  elif i == 2
#   undef i
#   define i 3
#   undef r3
#   undef p3
#   undef n3
#   define r3 (r2 | (1 << j2))
#   define p3 (p2 | (1 << 2 + j2))
#   define n3 (n2 | (1 << 9 - j2))
#   undef j3
#   define j3 0
#   include __FILE__
#   undef j3
#   define j3 1
#   include __FILE__
#   undef j3
#   define j3 2
#   include __FILE__
#   undef j3
#   define j3 3
#   include __FILE__
#   undef j3
#   define j3 4
#   include __FILE__
#   undef j3
#   define j3 5
#   include __FILE__
#   undef j3
#   define j3 6
#   include __FILE__
#   undef j3
#   define j3 7
#   include __FILE__
#   undef i
#   define i 2
#  elif i == 3
#   undef i
#   define i 4
#   undef r4
#   undef p4
#   undef n4
#   define r4 (r3 | (1 << j3))
#   define p4 (p3 | (1 << 3 + j3))
#   define n4 (n3 | (1 << 10 - j3))
#   undef j4
#   define j4 0
#   include __FILE__
#   undef j4
#   define j4 1
#   include __FILE__
#   undef j4
#   define j4 2
#   include __FILE__
#   undef j4
#   define j4 3
#   include __FILE__
#   undef j4
#   define j4 4
#   include __FILE__
#   undef j4
#   define j4 5
#   include __FILE__
#   undef j4
#   define j4 6
#   include __FILE__
#   undef j4
#   define j4 7
#   include __FILE__
#   undef i
#   define i 3
#  elif i == 4
#   undef i
#   define i 5
#   undef r5
#   undef p5
#   undef n5
#   define r5 (r4 | (1 << j4))
#   define p5 (p4 | (1 << 4 + j4))
#   define n5 (n4 | (1 << 11 - j4))
#   undef j5
#   define j5 0
#   include __FILE__
#   undef j5
#   define j5 1
#   include __FILE__
#   undef j5
#   define j5 2
#   include __FILE__
#   undef j5
#   define j5 3
#   include __FILE__
#   undef j5
#   define j5 4
#   include __FILE__
#   undef j5
#   define j5 5
#   include __FILE__
#   undef j5
#   define j5 6
#   include __FILE__
#   undef j5
#   define j5 7
#   include __FILE__
#   undef i
#   define i 4
#  elif i == 5
#   undef i
#   define i 6
#   undef r6
#   undef p6
#   undef n6
#   define r6 (r5 | (1 << j5))
#   define p6 (p5 | (1 << 5 + j5))
#   define n6 (n5 | (1 << 12 - j5))
#   undef j6
#   define j6 0
#   include __FILE__
#   undef j6
#   define j6 1
#   include __FILE__
#   undef j6
#   define j6 2
#   include __FILE__
#   undef j6
#   define j6 3
#   include __FILE__
#   undef j6
#   define j6 4
#   include __FILE__
#   undef j6
#   define j6 5
#   include __FILE__
#   undef j6
#   define j6 6
#   include __FILE__
#   undef j6
#   define j6 7
#   include __FILE__
#   undef i
#   define i 5
#  elif i == 6
#   undef i
#   define i 7
#   undef r7
#   undef p7
#   undef n7
#   define r7 (r6 | (1 << j6))
#   define p7 (p6 | (1 << 6 + j6))
#   define n7 (n6 | (1 << 13 - j6))
#   undef j7
#   define j7 0
#   include __FILE__
#   undef j7
#   define j7 1
#   include __FILE__
#   undef j7
#   define j7 2
#   include __FILE__
#   undef j7
#   define j7 3
#   include __FILE__
#   undef j7
#   define j7 4
#   include __FILE__
#   undef j7
#   define j7 5
#   include __FILE__
#   undef j7
#   define j7 6
#   include __FILE__
#   undef j7
#   define j7 7
#   include __FILE__
#   undef i
#   define i 6
#  elif i == 7
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           j0 + 1, j1 + 1, j2 + 1, j3 + 1, j4 + 1, j5 + 1, j6 + 1, j7 + 1);
#  endif
# endif
#else
#include <stdio.h>
#define _cat(a, b) a ## b
#define j_(i) _cat(j, i)
#define n_(i) _cat(n, i)
#define p_(i) _cat(p, i)
#define r_(i) _cat(r, i)
int main(void)
{
# define i 0
# define j0 0
# include __FILE__
# undef j0
# define j0 1
# include __FILE__
# undef j0
# define j0 2
# include __FILE__
# undef j0
# define j0 3
# include __FILE__
# undef j0
# define j0 4
# include __FILE__
# undef j0
# define j0 5
# include __FILE__
# undef j0
# define j0 6
# include __FILE__
# undef j0
# define j0 7
# include __FILE__
# undef j0
    return 0;
}
#endif

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

ภายในรหัส preprocessor ที่iและjระบุตำแหน่งปัจจุบันได้รับการพิจารณาในขณะที่r, pและnติดตามซึ่งจัดอันดับและเส้นทแยงมุมขณะนี้ไม่พร้อมใช้งานสำหรับตำแหน่ง อย่างไรก็ตามiยังเป็นสองเท่าเป็นตัวนับที่ทำเครื่องหมายระดับความลึกปัจจุบันของการเรียกซ้ำดังนั้นค่าอื่น ๆ ทั้งหมดจึงใช้ i เป็นตัวห้อยดังนั้นค่าของมันจะถูกเก็บไว้เมื่อกลับมาจากการเรียกซ้ำ (และเนื่องจากความยากลำบากอย่างร้ายแรงในการปรับเปลี่ยนค่าของสัญลักษณ์ตัวประมวลผลล่วงหน้าโดยไม่ต้องแทนที่อย่างสมบูรณ์)

โปรแกรมที่คอมไพล์พิมพ์ทั้งหมด 92 คำตอบ โซลูชั่นจะถูกฝังลงในไฟล์ที่เรียกทำงานได้โดยตรง เอาต์พุตตัวประมวลผลล่วงหน้ามีลักษณะดังนี้:

/* ... #included content from <stdio.h> ... */
int main(void)
{
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           0 + 1, 4 + 1, 7 + 1, 5 + 1, 2 + 1, 6 + 1, 1 + 1, 3 + 1);
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           0 + 1, 5 + 1, 7 + 1, 2 + 1, 6 + 1, 3 + 1, 1 + 1, 4 + 1);
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           0 + 1, 6 + 1, 3 + 1, 5 + 1, 7 + 1, 1 + 1, 4 + 1, 2 + 1);
    /* ... 88 more solutions ... */
    printf("(1 %d) (2 %d) (3 %d) (4 %d) (5 %d) (6 %d) (7 %d) (8 %d)\n",
           7 + 1, 3 + 1, 0 + 1, 2 + 1, 5 + 1, 1 + 1, 6 + 1, 4 + 1);
    return 0;
}

สามารถทำได้แม้ว่าจะไม่ชัดเจนก็ตาม


7

นี่คือโซลูชัน C ++ 11 ที่ไม่มีเทมเพลตใด ๆ :

constexpr int trypos(
    int work, int col, int row, int rows, int diags1, int diags2,
    int rowbit, int diag1bit, int diag2bit);

constexpr int place(
    int result, int work, int col, int row, int rows, int diags1, int diags2)
{
    return result != 0 ? result
        : col == 8 ? work
        : row == 8 ? 0
        : trypos(work, col, row, rows, diags1, diags2,
                 1 << row, 1 << (7 + col - row), 1 << (14 - col - row));
}

constexpr int trypos(
    int work, int col, int row, int rows, int diags1, int diags2,
    int rowbit, int diag1bit, int diag2bit)
{
    return !(rows & rowbit) && !(diags1 & diag1bit) && !(diags2 & diag2bit)
        ? place(
            place(0, work*10 + 8-row, col + 1, 0,
                  rows | rowbit, diags1 | diag1bit, diags2 | diag2bit),
            work, col, row + 1, rows, diags1, diags2)
        : place(0, work, col, row + 1, rows, diags1, diags2);
}

int places = place(0, 0, 0, 0, 0, 0, 0);

วิธีการแก้ปัญหาถูกเข้ารหัสเป็นตัวเลขทศนิยมเช่นเดียวกับในคำตอบของ FredOverflow GCC 4.7.1 รวบรวมไฟล์ข้างต้นเป็นแหล่งประกอบต่อไปนี้ด้วยg++ -S -std=c++11 8q.cpp:

    .file   "8q.cpp"
    .globl  places
    .data
    .align 4
    .type   places, @object
    .size   places, 4
places:
    .long   84136275
    .ident  "GCC: (GNU) 4.7.1"
    .section    .note.GNU-stack,"",@progbits

ค่าของสัญลักษณ์placesคือ 84136275 คือราชินีคนแรกที่ a8, ที่สองที่ b4 เป็นต้น


0

เทมเพลต c ++ ที่มีคลาสเทมเพลตเพียงคลาสเดียวเท่านั้นที่ถูกกำหนด:

template <int N, int mask, int mask2, int mask3, int remainDigit, bool fail>
struct EQ;

template <int N, int mask, int mask2, int mask3>
struct EQ<N, mask, mask2, mask3, 0, false> {
    enum _ { Output = (char [N])1 };
};

template <int N, int mask, int mask2, int mask3, int i>
struct EQ<N, mask, mask2, mask3, i, true> { };

template <int N, int mask, int mask2, int mask3, int i>
struct EQ<N, mask, mask2, mask3, i, false> {
    enum _ { _ = 
             sizeof(EQ<N*10+1, mask|(1<<1), mask2|(1<<(1+i)), mask3|(1<<(1+8-i)), i-1, 
               (bool)(mask&(1<<1)) || (bool)(mask2&(1<<(1+i))) || (bool)(mask3&(1<<(1+8-i)))>) +
             sizeof(EQ<N*10+2, mask|(1<<2), mask2|(1<<(2+i)), mask3|(1<<(2+8-i)), i-1, 
               (bool)(mask&(1<<2)) || (bool)(mask2&(1<<(2+i))) || (bool)(mask3&(1<<(2+8-i)))>) +
             sizeof(EQ<N*10+3, mask|(1<<3), mask2|(1<<(3+i)), mask3|(1<<(3+8-i)), i-1, 
               (bool)(mask&(1<<3)) || (bool)(mask2&(1<<(3+i))) || (bool)(mask3&(1<<(3+8-i)))>) +
             sizeof(EQ<N*10+4, mask|(1<<4), mask2|(1<<(4+i)), mask3|(1<<(4+8-i)), i-1, 
               (bool)(mask&(1<<4)) || (bool)(mask2&(1<<(4+i))) || (bool)(mask3&(1<<(4+8-i)))>) +
             sizeof(EQ<N*10+5, mask|(1<<5), mask2|(1<<(5+i)), mask3|(1<<(5+8-i)), i-1, 
               (bool)(mask&(1<<5)) || (bool)(mask2&(1<<(5+i))) || (bool)(mask3&(1<<(5+8-i)))>) +
             sizeof(EQ<N*10+6, mask|(1<<6), mask2|(1<<(6+i)), mask3|(1<<(6+8-i)), i-1, 
               (bool)(mask&(1<<6)) || (bool)(mask2&(1<<(6+i))) || (bool)(mask3&(1<<(6+8-i)))>) +
             sizeof(EQ<N*10+7, mask|(1<<7), mask2|(1<<(7+i)), mask3|(1<<(7+8-i)), i-1, 
               (bool)(mask&(1<<7)) || (bool)(mask2&(1<<(7+i))) || (bool)(mask3&(1<<(7+8-i)))>) +
             sizeof(EQ<N*10+8, mask|(1<<8), mask2|(1<<(8+i)), mask3|(1<<(8+8-i)), i-1, 
               (bool)(mask&(1<<8)) || (bool)(mask2&(1<<(8+i))) || (bool)(mask3&(1<<(8+8-i)))>)};
};
int main(int argc, _TCHAR* argv[])
{
    // output all solutions to eight queens problems as error messages
    sizeof(EQ<0, 0, 0, 0, 8, false>);
    return 0;
}

ดังนั้นข้อความแสดงข้อผิดพลาดจะดูเหมือน:

ข้อผิดพลาด C2440: 'type cast': ไม่สามารถแปลงจาก 'int' เป็น 'char [15863724]'

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