সি, 2765 (অনুকূল)
সম্পাদন করা
এখন সবই একটি সি সি ফাইলে। এটি কেবলমাত্র সর্বোত্তম সমাধানগুলি সন্ধান করে। তাদের সকলের অবশ্যই 15 টি বর্ণের 6 টি শব্দ এবং একটি 10-অক্ষরের শব্দ থাকতে হবে 8 টির 1 টি এবং দুটি শূন্যের 8 টি অক্ষর। তার জন্য আমাকে কেবল অভিধানের একটি ভগ্নাংশ লোড করতে হবে এবং আমাকে ফাঁকা দিয়ে 15 টি অক্ষরের শব্দ খুঁজতে হবে না। কোডটি একটি সাধারণ সম্পূর্ণ গভীরতা-প্রথম অনুসন্ধান।
#include <stdio.h>
#include <stdint.h>
#include <string.h>
struct w {
struct lc { uint64_t hi,lo; } lc;
char w[16];
} w15[6000], w10[40000];
int n15,n10;
struct lc pool = { 0x12122464612, 0x8624119232c4229 };
int pts[27] = {0,1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,1,1,1,1,4,4,8,4,10};
int f[27],fs[26], w15c[27],w15l[27][6000];
int count(struct lc a, int l) { return (l < 16 ? a.lo << 4 : a.hi) >> 4*(l&15) & 15; }
int matches_val(uint64_t a, uint64_t b) {
uint64_t mask = 0x1111111111111111ll;
return !((a - b ^ a ^ b) & mask);
}
int matches(struct lc all, struct lc a) { return matches_val(all.hi,a.hi) && matches_val(all.lo,a.lo); }
int picks[10];
void try(struct lc cur, int used, int level) {
int c, i, must;
if (level == 6) {
for (i = 0; i<27; i++) if (count(cur, i) && pts[i]>1) return;
for (i = 0; i < n10; i++) if(!(used & (1 << (w10[i].w[0] & 31))) && matches(w10[i].lc, cur)) {
for (c = 0; c<level; c++) printf("%s ",w15[picks[c]].w);
printf("%s\n",w10[i].w);
}
return;
}
for (i = 0; i < 26;i++) if (count(cur,fs[i])) break;
must = fs[i];
for (c = 0; c < w15c[must]; c++) { i = w15l[must][c]; if(!(used & (1 << (w15[i].w[0] & 31))) && matches(cur, w15[i].lc)) {
struct lc b = { cur.hi - w15[i].lc.hi, cur.lo - w15[i].lc.lo };
picks[level] = i;
try(b, used + (1 << (w15[i].w[0] & 31)), level+1);
}}
}
int cmpfs(int *a, int *b){return f[*a]-f[*b];}
void ins(struct w*w, char *s, int c) {
int i;
strcpy(w->w,s);
for (;*s;s++)
if (*s&16) w->lc.hi += 1ll << 4*(*s&15); else w->lc.lo += 1ll << 4*(*s&15) - 4;
if (c) for (i = 0; i < 27;i++) if (count(w->lc,i)) f[i]++, w15l[i][w15c[i]++] = w-w15;
}
int main() {
int i;
char s[20];
while(scanf("%s ",s)>0) {
if (strlen(s) == 15) ins(w15 + n15++,s,1);
if (strlen(s) == 10) ins(w10 + n10++,s,0);
}
for (i = 0; i < 26;i++) fs[i] = i+1;
qsort(fs, 26, sizeof(int), cmpfs);
try(pool, 0, 0);
}
ব্যবহার:
$time ./scrab <sowpods.txt
cc -O3 scrab.c -o scrab
JUXTAPOSITIONAL DEMISEMIQUAVERS ACKNOWLEDGEABLY WEATHERPROOFING CONVEYORIZATION FEATHERBEDDINGS LAURUSTINE
JUXTAPOSITIONAL DEMISEMIQUAVERS ACKNOWLEDGEABLY WEATHERPROOFING CONVEYORIZATION FEATHERBEDDINGS LUXURIATED
JUXTAPOSITIONAL DEMISEMIQUAVERS ACKNOWLEDGEABLY WEATHERPROOFING CONVEYORIZATION FEATHERBEDDINGS LUXURIATES
JUXTAPOSITIONAL DEMISEMIQUAVERS ACKNOWLEDGEABLY WEATHERPROOFING CONVEYORIZATION FEATHERBEDDINGS ULTRAQUIET
JUXTAPOSITIONAL DEMISEMIQUAVERS ACKNOWLEDGEABLY WEATHERPROOFING CONVEYORIZATION FEATHERBEDDINGS UTRICULATE
JUXTAPOSITIONAL DEMISEMIQUAVERS WEATHERPROOFING ACKNOWLEDGEABLY CONVEYORIZATION FEATHERBEDDINGS LAURUSTINE
JUXTAPOSITIONAL DEMISEMIQUAVERS WEATHERPROOFING ACKNOWLEDGEABLY CONVEYORIZATION FEATHERBEDDINGS LUXURIATED
JUXTAPOSITIONAL DEMISEMIQUAVERS WEATHERPROOFING ACKNOWLEDGEABLY CONVEYORIZATION FEATHERBEDDINGS LUXURIATES
JUXTAPOSITIONAL DEMISEMIQUAVERS WEATHERPROOFING ACKNOWLEDGEABLY CONVEYORIZATION FEATHERBEDDINGS ULTRAQUIET
JUXTAPOSITIONAL DEMISEMIQUAVERS WEATHERPROOFING ACKNOWLEDGEABLY CONVEYORIZATION FEATHERBEDDINGS UTRICULATE
OVERADJUSTMENTS QUODLIBETARIANS ACKNOWLEDGEABLY WEATHERPROOFING EXEMPLIFICATIVE HYDROGENIZATION RUBIACEOUS
OVERADJUSTMENTS QUODLIBETARIANS WEATHERPROOFING ACKNOWLEDGEABLY EXEMPLIFICATIVE HYDROGENIZATION RUBIACEOUS
real 0m1.754s
user 0m1.753s
sys 0m0.000s
প্রতিটি দ্রষ্টব্য দু'বার মুদ্রিত হয়েছে নোট করুন কারণ 15-অক্ষরের 'ডাব্লু' শব্দ যুক্ত করার সময় 2 টি অর্ডার তৈরি হয় কারণ সেখানে 2 'ডাব্লু' টাইল রয়েছে।
পয়েন্ট বিচ্ছেদের সাথে প্রথম সমাধানটি পাওয়া গেল:
JUXTAPOSITIONAL 465
DEMISEMIQUAVERS 480
ACKNOWLEDGEABLY 465
WEATHERPROOFING 405
CONVEYORIZATION 480
FEATHERBEDDINGS 390
LAURUSTINE (LAURU?TI?E) 80
no tiles left
সম্পাদনা: ব্যাখ্যা
সম্পূর্ণ স্থান অনুসন্ধান কী সম্ভব করে? একটি নতুন শব্দ যুক্ত করার সময় আমি কেবলমাত্র সেই শব্দগুলিকেই বিবেচনা করি যাতে বিরল বাকী অক্ষর থাকে। এই চিঠিটি যে কোনওভাবেই হওয়া উচিত (এবং একটি 15 অক্ষরের শব্দ যেহেতু এটি একটি 1-মানযুক্ত অক্ষর হবে, যদিও আমি এটির জন্য যাচাই করি না)। সুতরাং আমি শব্দগুলি দিয়ে শুরু করি J, Q, W, W, X, Z
যার চারপাশে গণনা রয়েছে 50, 100, 100, 100, 200, 500
। নিম্ন স্তরে আমি আরও কাট অফ পাই কারণ কিছু শব্দ অক্ষরের অভাবে মুছে ফেলা হয়। প্রতিটি স্তরের অনুসন্ধান গাছের প্রশস্ততা:
0: 1
1: 49
2: 3046
3: 102560
4: 724040
5: 803959
6: 3469
অপ্রচলিত সমাধানগুলি (15 টি অক্ষরের শব্দের বা ছোট শব্দে ফাঁকা) পরীক্ষা না করে অবশ্যই অনেকগুলি কাট অফ পাওয়া যায়। সুতরাং এটি ভাগ্যবান যে এই অভিধানটির সাহায্যে 2765 সমাধান অর্জন করা যেতে পারে (তবে এটি নিকটেই ছিল, 15 অক্ষরের শব্দের 2 টি সংমিশ্রণই একটি যুক্তিসঙ্গত বাকী অংশ দেয়)। অন্যদিকে, কম স্কোরিং সংমিশ্রণের জন্য কোডটি সংশোধন করা সহজ যেখানে সমস্ত অবশিষ্ট 10 টি অক্ষর 1-মূল্যবান নয়, যদিও এটি সর্বোত্তম সমাধান হতে পারে তা প্রমাণ করা আরও কঠিন।
এছাড়াও কোডটি অকাল অপটিমাইজেশনের ক্লাসিক কেসটি দেখায়। matches
ফাংশনের এই সংস্করণটি কোডটি কেবল 30% ধীর করে তোলে:
int matches(struct lc all, struct lc a) {
int i;
for (i = 1; i < 27; i++) if (count(a, i) > count(all, i)) return 0;
return 1;
}
আমি কীভাবে বিট যাদুটির সমান্তরাল তুলনাটি আমার মূল কোডের চেয়ে আরও ছোট করতে পারি তা বুঝতে পেরেছি (এই ক্ষেত্রে সর্বোচ্চ স্তন্যপান ব্যবহার করা যাবে না, তবে এটি কোনও সমস্যা নয়, কারণ 32 টির মধ্যে আমার কেবল 26 টি প্রয়োজন):
int matches_val(uint64_t a, uint64_t b) {
uint64_t mask = 0x1111111111111111ll;
return !((a - b ^ a ^ b) & mask);
}
তবে এটি শূন্য সুবিধা দেয়।
সম্পাদন করা
উপরের ব্যাখ্যাটি লিখে আমি বুঝতে পেরেছিলাম যে বেশিরভাগ সময় matches
ফাংশনে নেই এমন একটি নির্দিষ্ট চিঠি রয়েছে তাদের শব্দের তালিকা স্ক্যান করার জন্য ব্যয় হয় । তালিকাগুলি অগ্রণী গণনা 10x গতিবেগ দিয়েছে।