1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/**
* An implementation of an 'enzymatic programming' paradigm.
*/
DEBUG = true;
DEBUG = false;
Substrate = function(name_) {
this.name_ = name_;
this.items = [];
this.zymes = [];
this.currUid = 1;
};
Substrate.prototype = {
addItem: function(item) {
if (!item.__uid__) {
item.__uid__ = this.currUid;
this.currUid ++;
}
this.items.push(item);
},
addZyme: function(zyme) {
this.zymes.push(zyme);
if (!zyme.select) zyme.select = Zyme.prototype.select;
if (!zyme.process) zyme.process = Zyme.prototype.process;
},
solve: function() {
print("// Solving " + this._name + "...");
var startTime = Date.now();
var midTime = startTime;
var that = this;
function midComment() {
var curr = Date.now();
if (curr - midTime > 1000) {
print('// Working on ' + that.name_ + ', so far ' + ((curr-startTime)/1000).toString().substr(0,10) + ' seconds. Have ' + that.items.length + ' items.');
midTime = curr;
}
}
function finalComment() {
print('// Completed ' + that.name_ + ' in ' + ((Date.now() - startTime)/1000).toString().substr(0,10) + ' seconds.');
}
// Naive solver - sheer brute force.
// Assumes list of Zymes is non-changing.
var results = [];
while (true) {
if (DEBUG) print("Cycle start, " + this.items.length + " items.");
var hadProcessing = false;
for (var z = 0; z < this.zymes.length; z++) {
var zyme = this.zymes[z];
var selected = zyme.select(this.items);
if (selected.length > 0) {
if (DEBUG) print("Calling: " + (zyme.processItem ? zyme.processItem : zyme.process));
if (DEBUG) {
try {
print("Inputs: \n---\n\n" + outputs.map(JSON.stringify).join('\n\n') + '\n\n---');
} catch(e) {
print("Inputs: \n---\n\n" + outputs + '\n\n---');
}
}
hadProcessing = true;
this.items = this.items.filter(function(item) { return selected.indexOf(item) == -1 });
var outputs;
try {
outputs = zyme.process(selected);
} catch (e) {
print("Exception, current selected are: " + selected.map(dump).join('\n\n').substr(0,100));
print("Stack: " + new Error().stack);
throw e;
}
if (DEBUG) {
try {
print("Outputs: \n---\n\n" + outputs.map(JSON.stringify).join('\n\n') + '\n\n---');
} catch(e) {
print("Outputs: \n---\n\n" + outputs + '\n\n---');
}
}
if (outputs.length === 1 && outputs[0].__finalResult__) {
if (DEBUG) print("Solving complete: __finalResult__");
delete outputs[0].__finalResult__; // Might recycle this
delete outputs[0].__uid__;
finalComment();
return outputs[0];
}
results = results.concat(outputs.filter(function(output) { return !!output.__result__; }))
outputs.filter(function(output) { return !output.__result__; }).forEach(this.addItem, this);
results.forEach(function(output) {
delete output.__result__; // Might recycle these
delete output.__uid__;
});
}
}
if (this.items.length === 0) {
if (DEBUG) print("Solving complete: no remaining items");
finalComment();
return results;
}
if (!hadProcessing) {
print("Reached a dead end.");
this.items.forEach(function(item) {
print("remaining item:" + dump(item));
});
throw "failure";
}
midComment();
this.items = this.items.filter(function(item) { return item !== null; });
}
},
};
Zyme = function() { };
Zyme.prototype = {
select: function(items) {
return items.filter(this.selectItem, this);
},
process: function(items) {
var ret = [];
items.forEach(function(item) { ret = ret.concat(this.processItem(item)) }, this);
return ret;
},
};
|