كما كتبت لغز الكلمات المتقاطعة اليابانية في 4 ساعات

أنظر بإسهاب إلى قائمة الدورات التي عقدها تلاميذ المدارس التي وضعها زملاء من Sirius مؤخرًا ... فما هذا؟ "البحث عن كائنات اندماجية باستخدام SAT-solvers"؟ "قمنا بصنع سودوكو ، كلمات متقاطعة يابانية والمزيد؟"

تنبثق الفكرة من أن مشاكل NP الشاملة يمكن اختزالها لبعضها البعض ، وعلى وجه الخصوص ، يمكن اختزالها للبحث عن جدوى صيغة منطقية . عبّر أحد مؤلفي هبر عن هذه الفكرة هنا ، وبصراحة ، إنها مثل السحر.

بالطبع ، كشخص أكمل دورة في الرياضيات المنفصلة وتعقيد الخوارزميات ، أعلم نظريًا أن المهام يمكن اختزالها مع بعضها البعض. ولكن من الصعب عادةً القيام بذلك ، ومن الأفضل أن أوصي بكلمة للأساتذة والأشخاص الأذكياء الآخرين.

ولكن بعد ذلك يتم عرضه على ... SCHOOLCHILDREN! في الداخل ، بدأ الخرام في إثارة الإبداع وقال: "حسنًا ، ربما لا يكون من الصعب تثبيته بمجرد عرض الطلاب. لا يمكنني معرفة ذلك ؟؟ انظروا ، يعدون بأنهم سيستخدمون مكتبة Python ، لكنني أعرف بشكل عام الثعبان ... "

وكان الوقت حوالي الساعة 9 مساءً ، وهو ما خفف إلى حد ما من نظري النقدي في تعقيد المشكلة ... (في الواقع ، المزيد من سجلات البرمجة لمدة 4 ساعات)

21:02 المرحلة الأولى من المهمة - أحاول تثبيت المكتبة في Python. من تجربة الشبكات العصبية ، أعلم بالفعل أن الشفرة أحيانًا تستغرق وقتًا أقل من تكوين الحزم.

باستخدام تثبيت النقطة الكلاسيكية pycosat غير مثبت ، فإنه ينتج خطأ في روح Microsoft Visual C ++ 14.0 مطلوب .

نتسلق للبحث عن مصدر المشكلة ، نصل إلى Stackoverflow ، حيث نجد رابطًا صغيرًا لأدوات البناء Visual C ++ 2015 المطلوبة ، بما في ذلك على ما يبدو مترجم C ++.

تنزيل ، محاولة تثبيت ... رائع ، يتطلب 4 غيغابايت! أنا في الحقيقة أحتاج فقط إلى مترجم ، لكن حسنًا.

أثناء تنزيل هذا الشيء وتثبيته ، نتبع الروابط الموجودة في البرنامج المنشور من Sirius ... نعم ، ليس كثيرًا - أمثلة على مشاريع Python وقائمة بالمهام المحتملة للدورة التدريبية. لا توجد عروض تقديمية ، ولا توجد مقاطع فيديو لفهم كيفية العمل مع المكتبة بسرعة.

حسنًا ، لنبدأ بتحليل الأمثلة. نذهب إلى queens_pycosat.py ... واو ، على طول الطريق ، هذا هو الحل للمشكلة المألوفة المتمثلة في وضع الملكات على رقعة الشطرنج (المهمة هي ترتيب 8 ملكات حتى لا يتغلبوا على بعضهم البعض).

21: 10-21: 30 نحن نفهم ونحاول البدء.

يبدأ تتبع المنطق العام:
SAT- () (1, 2, 3),(-1, 2 ..), (True/False).

, , .

( , ); , , 8x8 = 64 , .

(1 2 3… 8) — 1 . — [1,2,3...8]
— (9… 16) ..

— 1 !
[ 1 2] ( — ). [-1,-2],[-1,-3] .

, , . , .

( ) — (1 2… 8) ( 1 2) (...). , — .

نعم ، لم أكن ذكيًا جدًا على الفور ، الآن بعد أن اكتشفته ...

بشكل عام ، نحن ننسخ رمز التدريس لأنفسنا. للتأكد من أننا نفهم شيئًا ما ، أوقف التحقق من الأقطار - ثم تتحول المهمة إلى مهمة حول الرخاء.

نبدأ ، نتلقى: يعمل! 21:35 بعد التعرف قليلاً على وثائق المكتبة ، نجد أن هناك تحديات في إيجاد حل واحد أو جميع الحلول. قل لي ، يا صديقي العزيز ، كم عدد الترتيبات الرخ الموجودة على لوحة 8x8؟ هل ستجد كل شيء؟ اعتقدت الآلة لبعض الوقت ، وبدأت في البحث في جدول العوامل. بعد دقيقة ، أجاب حلالا - "تم العثور على 40320 حل". تحقق - حقا 8 !، كل شيء صحيح.

| | | | | | | |x|
| | | | | | |x| |
| | | | | |x| | |
| | | | |x| | | |
| | | |x| | | | |
| | |x| | | | | |
| |x| | | | | | |
|x| | | | | | | |











أزلت شرط أن الرخ لا يصطدم ببعضهما البعض عموديا ... ولكن كم سيكون عليه الآن؟ يجب أن يكون 8 ^ 8 = 16777216. ثم فجر لي أنه سيستغرق وقتا طويلا للعد - نحن نقاطع العملية.

وجدت أيضًا طريقة سريعة لاشتقاق 4 حلول بدون حساب كل شيء - من كل شيء في نفس المكتبة. يتم ذلك - نجد حلاً ، وبعد ذلك نضيفه إلى استثناءات الصيغة المنطقية ...

كيفية استخلاص عدة حلول في الثعبان
for cnter in range(4):
  sol = pycosat.solve(clauses)
  if isinstance(sol, list):
    print(sol)
    clauses.append([-x for x in sol]) #   -      
  else: #    - 
    return
#     ,    ,   .


بشكل عام ، لدينا بعض الحلول الإضافية "لمشكلة الرخ": 21:45 أولاً : بشكل عام ، كل شيء واضح ، إن وجد ، يمكنني الآن ربطه. سأقرأ كتابًا وسبا ... بداية إبداعية: حسنًا ، أنت تفهم كيف يعمل كل شيء. ودعنا نكتب لغزًا بسيطًا للكلمات المتقاطعة من الكلمات المتقاطعة اليابانية! خذ أبسط حالة - في كل صف وعمود لن يكون هناك أكثر من رقم واحد (وبالتالي كتلة واحدة). ما عليك سوى البحث من خلال الخيارات الممكنة للصف / العمود ، فهو سريع هنا ، ثم تحميله في حلالا. دعنا نفعل ذلك ، هاه؟ لي: ( بدون الشعور بالكمائن ) حسنًا ، هيا ... يبدو أن الحقيقة ليست لفترة طويلة ... من أجل البساطة ، نأخذ فقط الكلمات المتقاطعة NxN المربعة - في نفس الوقت ، يمكنك أن تأخذ كود الإخراج جاهزًا وتفكر في المكان غير الأفقي والرأسي ...

| | | | | | | |x|
| | | | | | |x| |
| | | | | |x| | |
| | | | |x| | | |
| | | |x| | | | |
| |x| | | | | | |
| | |x| | | | | |
|x| | | | | | | |











22:10 لا يعمل: ((
نحن نحاول استخدام الكلمات المتقاطعة 3x3 ، بالتنسيق 1-0-1 (في حين أن الكتل أفقية فقط ، فإننا لا نأخذ القطاعات في الاعتبار). إنها تعطي جميع الخلايا الفارغة ، والعدوى ، ولا تأخذ في الاعتبار الكتل المملوءة ...

حسنًا بالتفصيل نتعمق في تنسيق نقل البيانات إلى حلالا ، ثم شيء ما ، بعبارة ملطفة ، غير متوقع ...

, «-» ?

/ /, — . , .

[1] 3 , :
[X__],[_X_],[__X]
, ,
[1,-2,-3],[-1,2,-3],[-1,-2,3]

, …
:
[1 -2 -3] [-1, 2...] [...]

, . , . — , !

كمين. في الواقع ، هناك خياران - إما للتوصل إلى شروط أحجية الكلمات المتقاطعة في KNF ، أو للتوصل إلى كيفية تحويل DNF إلى KNF (حسنًا ، كان يجب على أحد التفكير في ذلك ، خاصة وأن كلاهما صيغ منطقية!)

22:50 انتهيت من الوجبة الخفيفة. لم أفكر في كيفية تهيئة الظروف ل KNF (وجدت لاحقًا أنه تم وصفها في المقالة ، ولكن كان وقتًا طويلاً لبرمجتها ، وبصراحة ، غير رياضي).

لذلك نحن نبحث عن محول من DNF إلى CNF. الأوصاف الرسمية للتحولات في الأسلوب الأكاديمي متناثرة على الإنترنت ... لماذا أحتاجها؟ أنا بالتأكيد لن ألتزم بها الآن ، سأقوم بحل المشكلة. لذا ، نرى مكتبة Python الوحيدة (!) التي تحمل الاسم والوظائف المناسبة. الآن سنتصل ...

23:10إنه يعمل بشكل مضحك - فهو يصنع متغيرات إضافية ، ومن خلالها يجلب DNF إلى CNF. على ما يبدو ، صنع KNF بصراحة أمر صعب للغاية ...

لذا ، فهو أيضًا لا يعمل! ما الأمر؟
نقدم إدخال اختبار DNF: lstall = [[1،2،3]]. أي أننا نتوقع أن يكون [1،2،3] فقط (يتوافق مع السطر الكامل [XXX]) حلاً صالحًا. تقدم

المكتبة KNF: cnf = [[-1، -2، -3، 4]، [1 ، -4]، [2، -4]، [3، -4]]
هذا ليس واضحًا ولكنه مثير للاهتمام. حسنًا ، لنفترض أنني أصدقك ...

نطلب من pycosat إيجاد جميع حلول cnf:
[1، 2، 3، 4]
[1، 2، -3، -4]
[1، -2، -3، -4]
[1 ، -2، 3، -4]
[-1، -2، -3، -4]
[-1، -2، 3، -4]
[-1، 2، -3، -4]
[-1، 2 ، 3 ، -4]

بدلاً من المتوقع ، هناك ثمانية منهم! ماذا أفعل؟

, , 4 True. ?

: cnf2 = [[-1, -2, -3, 4], [1, -4], [2, -4], [3, -4], [4]]
pycosat cnf2:
1: [1, 2, 3, 4]

, , ! , , .
— !

23:10 هي تقرر! هنا 1-3-1 الكلمات المتقاطعة عموديا وأفقيا: هنا حل مزدوج للكلمة المتقاطعة 1-0-1 عموديا وأفقيا: أنا: إذن ، كل شيء يعمل بالنسبة لي ، لقد انتهيت. واو ، إنها بالفعل الساعة 11 مساءً سبا ... البدء الإبداعي: ​​هل تفهم أنه لم يتبق لديك سوى القليل لحل أي كلمات متقاطعة يابانية؟ من الضروري فقط كتابة إجراء تعاودي واحد سيعطي جميع خيارات الخط ليس لكتلة واحدة ، ولكن لـ N ... Me: حسنًا ... يبدو الأمر سهلاً ، نعم ... 00:00 في منتصف الليل ، طهي الرأس بالفعل ليس جيدًا جدًا ، لكني أستمر في تصحيح الأخطاء العودية. مصطلحات الكلمات المتقاطعة اليابانية - بين الكتل يجب أن يكون هناك مسافة واحدة على الأقل ، ولكن قد يكون هناك أكثر من واحد.

| |x| |
|x|x|x|
| |x| |




1
| | |x|
| | | |
|x| | |
2
|x| | |
| | | |
| | |x|












لذا ، في ظل شرط [1،2،1] لـ 6 خلايا ، يجب أن ينشئ البرنامج الخيار الوحيد
[X_XX_X] ، ول
7 خلايا هناك بالفعل 4 خيارات:
[X_XX_X_] ،
[X_XX__X] ،
[X__XX_X] ،
[_X_XX_X] ،

طوال الوقت أنا أحسب عن طريق الخطأ موقع الخلايا بواسطة خلية واحدة ، وإلى الجحيم - من الأسهل البدء والإصلاح من التفكير ...

00:30 هل يعمل؟ ماذا للتحقق؟ لذا ، من أين تحصل على وصف موجه للكلمات المتقاطعة ... على هذا الموقع ، لا ، على هذا - لا ... حسنًا ، إلى الجحيم ، سأقاطع الأقلام. 00:50 إنه يعمل حقًا O_O إليك سلطعون مع jcrosswords.ru/crossword/65

3x3
rows = [[1,1],[0],[1,1]]
cols = [[1,1],[0],[1,1]]

:
|X| |X|
| | | |
|X| |X|

4x4
rows = [[1,1],[0],[0],[1,1]]
cols = [[1],[1],[1],[1]]

:
1
| |X| |X|
| | | | |
| | | | |
|X| |X| |
2
|X| |X| |
| | | | |
| | | | |
| |X| |X|







قرر من قبل بلدي حلالا. الحد الأقصى للحجم الذي تم اختباره هو 10x10 ، والآن أنا كسول جدًا بالنسبة لي لمقاطعة المزيد من الكلمات المتقاطعة في البرنامج ... - أنا: واو ، إنه بالفعل واحد في الصباح! انتظر ، استغرق الأمر 4 ساعات فقط من اللحظة التي لم أكن أعرف فيها شيئًا عن SAT-solver؟ لذا ، كيف كان ذلك على الإطلاق؟ (تتم كتابة الملاحظات السريعة حول ما حدث ...)

|x|_|x|_|_|_|_|x|_|x|
|x|x|x|_|_|_|_|x|x|x|
|_|x|_|_|_|_|_|_|x|_|
|_|x|_|x|_|_|x|_|x|_|
|_|x|x|x|x|x|x|x|x|_|
|_|_|x|x|x|x|x|x|_|_|
|x|x|x|x|x|x|x|x|x|x|
|_|_|x|x|x|x|x|x|_|_|
|x|x|_|x|x|x|x|_|x|x|
|x|_|_|_|_|_|_|_|_|x|








خاتمة.

صباح . على هبر تم العثور على مقال عن حلال على الصدأ . التنزيل من الألغاز المتقاطعة لا يعمل ، ولكن بعد الانتقال إلى مقالة Github المحددة في المقالة ، نجد رابطًا مخفيًا لتصدير الكلمات المتقاطعة بتنسيق يمكن قراءته آليًا على موقع ويب Webpbn للكلمات المتقاطعة . إن خيار "تنسيق للنسخة 1 من Kyle Keen's Python solver" مناسب لنا ، وهو نفس خيارنا. عندما لا تحتاج إلى مقاطعة الكلمات المتقاطعة بالأقلام ، تسير الأمور بشكل أسرع. يصبح من الواضح بسرعة أن الحد الأقصى الذي يستطيع الحل حله هو الكلمات المتقاطعة في منطقة 30x30. المشكلة الرئيسية هي جيل متغيرات الخطوط الفردية ، في حالة كومة من كتل هذه الشروط ، كثيرًا جدًا ويبدأ كل شيء في التباطؤ:



1. أولاً ، يستغرق إنشاء خيارات السلسلة وقتًا طويلاً. يستغرق إنشاء جميع الخيارات فقط لسلسلة [2،1،3،1،4] من الطول 60 بالفعل حوالي نصف دقيقة ... (هناك 2118760 منهم ، إذا كان أي شخص مهتمًا)
2. أيضًا ، فإن تحويل DNF-> CNF يخلق العديد من الشروط ومتغيرات إضافية ...

ولكن إذا كان هناك عدد قليل من الكتل ، فيمكن حتى حل الكلمات المتقاطعة الكبيرة في وقت ذي معنى.

القطة - كل شيء على ما يرام
20x20
51511 clauses...
2851 last var number
--- 0.05186057090759277 seconds for clauses gen ---
1
| | |X|X| | | | | | | | | | | | | | | | |
| |X|X| | | | | | | | | | | | | | | | | |
| |X| | | | | | | | | | | | | | | | | | |
| |X| | | | | | | | | | | | | | | | | | |
| |X| | | | | |X|X|X| | | | | | | | | | |
|X|X| | | | |X|X|X|X|X| | | | | | | | | |
|X| | | | |X|X|X|X|X|X|X| | | |X| | | |X|
|X| | | | |X|X|X|X|X|X|X|X| | |X|X| |X|X|
|X| | | |X|X|X|X|X|X|X|X|X| | |X|X|X|X|X|
|X|X| | |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|
| |X| |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|
| |X|X|X|X|X|X|X| |X|X|X|X|X|X|X|X|X|X|X|
| | |X|X|X|X|X| | | |X|X|X|X|X| |X|X|X| |
| | |X|X|X|X|X| | | |X|X|X|X| | | | | | |
| | | |X|X|X| | | | | |X|X|X| | | | | | |
| | | |X|X| | | | | | |X|X| | | | | | | |
| | |X|X| | | | | | | | |X| | | | | | | |
| | |X| | | | | | | | | |X| | | | | | | |
| | |X|X| | | | | | | | |X|X| | | | | | |
| | |X|X| | | | | | | | |X|X| | | | | | |
--- 0.02073383331298828 seconds for solve ---


رغبة في اختبار المزيد من الكلمات المتقاطعة ، قام بمحاذاة بسرعة - يتم تقليل أي كلمة متقاطعة إلى مربع عندما نملأ الأسطر المتبقية بالأصفار. نعم ، إنها ليست مثالية ، ولكني الآن مترددة في إعادة الرمز ...

حصان - 30x38
22
13622799 clauses... -
350737 last var number
--- 14.18206787109375 seconds for clauses gen ---
1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |X|X|X| | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | |X|X|X|X|X|X|X| | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | | | | |X|X|X|X|X|X|X| | | |
| | | | | | | | | | | | | | | | | | | | | | | | | |X|X|X|X|X|X|X|X| |X|X| | |
| | | | | | | | | | | | | | | | | | | | | | | | | | |X|X|X|X|X|X|X|X|X|X|X| |
| | | | | | | | | | | | | | | | | | | | | | | |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|
| | | | | | | | | | | | | | | | | | | | | | | | |X|X|X|X|X|X|X|X| |X|X|X|X|X|
| | | | | | | | | | | | | | | | | | | | | | | | |X|X|X|X|X|X|X| | | | | |X| |
| | | | | | | | | | |X|X|X|X| | | | | | | | | |X|X|X|X|X|X|X|X| | | | | | | |
| | | | | | | | |X|X|X|X|X|X|X|X|X| | | |X|X|X|X|X|X|X|X|X|X| | | | | | | | |
| | | | | | |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X| | | | | | | | |
| | | | | |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X| | | | | | | | | |
| | | | |X|X|X| |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X| | | | | | | | | |
| | | |X|X|X| | |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X| | | | | | | | | |
| | |X|X|X| | | |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X| | | | |
| |X|X|X| | | |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X| | | |
|X|X|X|X| | | |X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X| | | |X|X| | | |
| |X|X| | | |X|X|X|X|X| | | | |X|X|X|X|X|X|X|X|X|X|X|X| | | | | | |X|X| | | |
| | |X| | | |X|X|X|X| |X| | | | | | |X|X|X|X|X|X| | | |X| | | | | |X|X| | | |
| | | | | |X|X|X|X| |X|X| | | | | | | | | | | | | |X|X|X| | | | | |X|X| | | |
| | | | |X|X|X|X| |X|X| | | | | | | | | | | | | | |X|X|X| | | | | |X|X| | | |
| | | | |X|X|X| | |X|X| | | | | | | | | | | | | | | |X|X| | | | | |X|X| | | |
| | | | |X|X| | | |X|X| | | | | | | | | | | | | | | |X|X| | | | |X|X|X| | | |
| | | |X|X|X| | | | |X|X| | | | | | | | | | | | | | |X|X| | | | |X|X| | | | |
| | | |X|X| | | | | |X|X| | | | | | | | | | | | | | |X|X| | | | |X| | | | | |
| | | |X|X| | | | | |X|X| | | | | | | | | | | | | | |X|X| | | | | | | | | | |
| | | |X|X| | | | | | |X|X| | | | | | | | | | | | | |X|X| | | | | | | | | | |
| | | |X|X| | | | | | |X|X| | | | | | | | | | | | | |X|X| | | | | | | | | | |
| | | | |X|X| | | | | | |X|X| | | | | | | | | | | | | |X|X| | | | | | | | | |
| | | | |X|X|X| | | | | |X|X|X| | | | | | | | | | | | |X|X|X| | | | | | | | |

--- 17.535892963409424 seconds for solve ---



في المنشور الأصلي عن SAT-solver ، يتم إنشاء الشروط والمتغيرات بأمانة أكثر - لذلك ، هناك حل أسرع وربما يستغرق ذاكرة أقل. عند اتخاذ قرار بشأن الحصان ، يأخذني حوالي 2.7 غيغابايت من ذاكرة الوصول العشوائي ، ويستغرق بعض الأشياء المعقدة لجميع الـ 12 المثبتة ، ثم يبدأوا في التبديل المحموم إلى القرص ...

المزيد من الاستنتاجات:

1. لقد بزغ لي لماذا تعد الأمثلة السريعة على pycosat هي حلول Sudoku. من السهل جدًا وضع قواعد Sudoku على حلال ، لأنك لست بحاجة إلى وصف العلاقة المعقدة بين الكتل والخلايا ، وبشكل أساسي فقط الشروط "كل رقم في كل صف" و "رقم واحد فقط في صف واحد".
لكني أحب سودوكو أقل من ذلك بكثير ، لذلك لا أندم على القرار الذي اخترته.

2. أحببت كيف يمكنك المزج بين DNF و CNF. إذا كنت لا ترغب في كتابة الشروط الصحيحة ، فلا تفعل ؛ ما عليك سوى إنشاء جميع الخيارات. بالطبع ، هذا ليس الأمثل ، لكنه يعمل.

بالطبع ، لم أقم بتعيين سجلات لسرعة حل الكلمات المتقاطعة ، ولكن قضيت وقتًا ممتعًا. أهم شيء يمكنني القيام به! :) ما أتمنى لك أيضا!

All Articles