Skip to content

Commit f1f85b6

Browse files
Word ladder
Signed-off-by: begeekmyfriend <begeekmyfriend@gmail.com>
1 parent fd65200 commit f1f85b6

File tree

2 files changed

+321
-0
lines changed

2 files changed

+321
-0
lines changed

126_word_ladder_ii/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
all:
2+
gcc -O2 -o test word_ladder.c

126_word_ladder_ii/word_ladder.c

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
#define container_of(ptr, type, member) \
6+
((type *)((char *)(ptr) - (size_t)&(((type *)0)->member)))
7+
8+
#define list_entry(ptr, type, member) \
9+
container_of(ptr, type, member)
10+
11+
#define list_first_entry(ptr, type, field) list_entry((ptr)->next, type, field)
12+
#define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field)
13+
14+
#define list_for_each(p, head) \
15+
for (p = (head)->next; p != (head); p = p->next)
16+
17+
#define list_for_each_safe(p, n, head) \
18+
for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next)
19+
20+
#define hlist_for_each(pos, head) \
21+
for (pos = (head)->first; pos; pos = pos->next)
22+
23+
#define hlist_for_each_safe(pos, n, head) \
24+
for (pos = (head)->first; pos && ({ n = pos->next; true; }); pos = n)
25+
26+
struct hlist_node;
27+
28+
struct hlist_head {
29+
struct hlist_node *first;
30+
};
31+
32+
struct hlist_node {
33+
struct hlist_node *next, **pprev;
34+
};
35+
36+
static inline void INIT_HLIST_HEAD(struct hlist_head *h) {
37+
h->first = NULL;
38+
}
39+
40+
static inline void INIT_HLIST_NODE(struct hlist_node *n) {
41+
n->next = NULL;
42+
n->pprev = NULL;
43+
}
44+
45+
static inline int hlist_empty(struct hlist_head *h) {
46+
return !h->first;
47+
}
48+
49+
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
50+
{
51+
if (h->first != NULL) {
52+
h->first->pprev = &n->next;
53+
}
54+
n->next = h->first;
55+
n->pprev = &h->first;
56+
h->first = n;
57+
}
58+
59+
struct list_head {
60+
struct list_head *next, *prev;
61+
};
62+
63+
static inline void
64+
INIT_LIST_HEAD(struct list_head *list)
65+
{
66+
list->next = list->prev = list;
67+
}
68+
69+
static inline int
70+
list_empty(const struct list_head *head)
71+
{
72+
return (head->next == head);
73+
}
74+
75+
static inline void
76+
__list_add(struct list_head *new, struct list_head *prev, struct list_head *next)
77+
{
78+
next->prev = new;
79+
new->next = next;
80+
new->prev = prev;
81+
prev->next = new;
82+
}
83+
84+
static inline void
85+
list_add(struct list_head *_new, struct list_head *head)
86+
{
87+
__list_add(_new, head, head->next);
88+
}
89+
90+
static inline void
91+
list_add_tail(struct list_head *_new, struct list_head *head)
92+
{
93+
__list_add(_new, head->prev, head);
94+
}
95+
96+
static inline void
97+
__list_del(struct list_head *entry)
98+
{
99+
entry->next->prev = entry->prev;
100+
entry->prev->next = entry->next;
101+
}
102+
103+
static inline void
104+
list_del(struct list_head *entry)
105+
{
106+
__list_del(entry);
107+
entry->next = entry->prev = NULL;
108+
}
109+
110+
struct word_node {
111+
int step;
112+
char *word;
113+
struct hlist_node node;
114+
};
115+
116+
struct word_tree {
117+
char *word;
118+
struct list_head sibling;
119+
struct list_head link;
120+
struct word_tree **parents;
121+
int par_num;
122+
int par_cap;
123+
int step;
124+
};
125+
126+
static int BKDRHash(char* str, int size)
127+
{
128+
int seed = 131; // 31 131 1313 13131 131313 etc..
129+
unsigned int hash = 0 ;
130+
while (*str != '\0') {
131+
hash = hash * seed + (*str++);
132+
}
133+
return hash % size;
134+
}
135+
136+
static struct word_node *find(char *word, struct hlist_head *hhead, int size, int step)
137+
{
138+
struct hlist_node *p;
139+
int hash = BKDRHash(word, size);
140+
hlist_for_each(p, &hhead[hash]) {
141+
struct word_node *node = list_entry(p, struct word_node, node);
142+
if (!strcmp(node->word, word)) {
143+
if (node->step == 0 || node->step == step) {
144+
return node;
145+
}
146+
}
147+
}
148+
return NULL;
149+
}
150+
151+
static void parent_add(struct word_tree *parent, struct word_tree *child)
152+
{
153+
if (child->par_num + 1 > child->par_cap) {
154+
child->par_cap *= 2;
155+
struct word_tree **parents = malloc(child->par_cap * sizeof(void *));
156+
memcpy(parents, child->parents, child->par_num * sizeof(void *));
157+
free(child->parents);
158+
child->parents = parents;
159+
}
160+
child->parents[child->par_num++] = parent;
161+
}
162+
163+
/**
164+
* * Return an array of arrays of size *returnSize.
165+
* * The sizes of the arrays are returned as *columnSizes array.
166+
* * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
167+
* */
168+
static char*** findLadders(char* beginWord, char* endWord, char** wordList, int wordListSize, int** columnSizes, int* returnSize)
169+
{
170+
int i, j, k;
171+
int len = strlen(beginWord);
172+
int hashsize = wordListSize * 2;
173+
char *word = malloc(len + 1);
174+
175+
struct hlist_head *hhead = malloc(hashsize * sizeof(*hhead));
176+
for (i = 0; i < hashsize; i++) {
177+
INIT_HLIST_HEAD(hhead + i);
178+
}
179+
180+
struct list_head *level_heads = malloc(wordListSize * sizeof(*level_heads));
181+
for (i = 0; i < wordListSize; i++) {
182+
INIT_LIST_HEAD(&level_heads[i]);
183+
}
184+
185+
/* Add into hash list */
186+
struct word_node *node;
187+
for (i = 0; i < wordListSize; i++) {
188+
node = malloc(sizeof(*node));
189+
node->word = wordList[i];
190+
node->step = 0;
191+
int hash = BKDRHash(wordList[i], hashsize);
192+
hlist_add_head(&node->node, &hhead[hash]);
193+
}
194+
195+
struct list_head *p, queue;
196+
INIT_LIST_HEAD(&queue);
197+
198+
struct word_tree *root = malloc(sizeof(*root));
199+
root->word = beginWord;
200+
root->step = 1;
201+
root->par_cap = 1;
202+
root->par_num = 1;
203+
root->parents = malloc(sizeof(void *));
204+
root->parents[0] = NULL;
205+
list_add_tail(&root->sibling, &level_heads[0]);
206+
node = find(beginWord, hhead, hashsize, 1);
207+
if (node != NULL) {
208+
node->step = 1;
209+
}
210+
211+
struct word_tree *first = root;
212+
while (strcmp(first->word, endWord)) {
213+
strcpy(word, first->word);
214+
for (i = 0; i < len; i++) {
215+
char c;
216+
char o = word[i];
217+
for (c = 'a'; c <= 'z'; c++) {
218+
word[i] = c;
219+
node = find(word, hhead, hashsize, first->step + 1);
220+
if (node != NULL) {
221+
int enqueue = 1;
222+
list_for_each(p, &level_heads[first->step]) {
223+
struct word_tree *w = list_entry(p, struct word_tree, sibling);
224+
if (!strcmp(w->word, node->word)) {
225+
enqueue = 0;
226+
parent_add(first, w);
227+
break;
228+
}
229+
}
230+
231+
if (enqueue) {
232+
node->step = first->step + 1;
233+
struct word_tree *new = malloc(sizeof(*new));
234+
new->word = node->word;
235+
new->step = node->step;
236+
new->par_cap = 10;
237+
new->par_num = 0;
238+
new->parents = malloc(new->par_cap * sizeof(void *));
239+
list_add_tail(&new->sibling, &level_heads[first->step]);
240+
list_add_tail(&new->link, &queue);
241+
parent_add(first, new);
242+
}
243+
}
244+
}
245+
word[i] = o;
246+
}
247+
248+
if (list_empty(&queue)) {
249+
*returnSize = 0;
250+
return NULL;
251+
} else {
252+
first = list_first_entry(&queue, struct word_tree, link);
253+
list_del(&first->link);
254+
}
255+
}
256+
257+
i = 0;
258+
int size = first->step;
259+
char ***results = malloc(1000 * sizeof(char **));
260+
int *indexes = malloc(size * sizeof(int));
261+
memset(indexes, 0, size * sizeof(int));
262+
struct word_tree **nodes = malloc(size * sizeof(*nodes));
263+
list_for_each(p, &level_heads[size - 1]) {
264+
struct word_tree *end = list_entry(p, struct word_tree, sibling);
265+
if (!strcmp(end->word, endWord)) {
266+
int move_on = 1;
267+
while (move_on) {
268+
move_on = 0;
269+
struct word_tree *w = end;
270+
char **list = results[i] = malloc(size * sizeof(char *));
271+
for (j = size - 1; j >= 0; j--) {
272+
list[j] = malloc(len + 1);
273+
strcpy(list[j], w->word);
274+
nodes[j] = w;
275+
w = w->parents[indexes[j]];
276+
}
277+
278+
/* Switch to another branch */
279+
for (j = 0; j < size; j++) {
280+
if (indexes[j] < nodes[j]->par_num - 1) {
281+
indexes[j]++;
282+
/* Reset indexes of parents */
283+
memset(indexes, 0, j * sizeof(int));
284+
move_on = 1;
285+
break;
286+
}
287+
}
288+
289+
i++;
290+
}
291+
}
292+
}
293+
294+
*columnSizes = malloc(i * sizeof(int));
295+
for (j = 0; j < i; j++) {
296+
(*columnSizes)[j] = size;
297+
}
298+
*returnSize = i;
299+
return results;
300+
}
301+
302+
int main(int argc, char **argv)
303+
{
304+
if (argc < 3) {
305+
fprintf(stderr, "Usage: ./test begin end dict...\n");
306+
exit(-1);
307+
}
308+
309+
int i, j, *sizes, count = 0;
310+
char ***lists = findLadders(argv[1], argv[2], argv + 3, argc - 3, &sizes, &count);
311+
for (i = 0; i < count; i++) {
312+
for (j = 0; j < sizes[i]; j++) {
313+
printf("%s ", lists[i][j]);
314+
}
315+
printf("\n");
316+
}
317+
318+
return 0;
319+
}

0 commit comments

Comments
 (0)