/usr/share/yacas/examples/wordproblems.ys is in yacas 1.3.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | /// Solve aritmetic problems written in (limited) English
///
/// Supported words:
/// a an the is are and person persons object objects many has had ate gave to some made
/// See coding.book section "Example: Using rules with special syntax operators creatively"
Prefix("a", 10);
Prefix("an", 10);
Infix("to", 15);
Prefix("the", 10);
Prefix("many", 35); // many apples and pears
Infix("is", 20);
Infix("had", 20);
Infix("has", 20);
Infix("ate", 20);
Infix("gave", 20);
Infix("made", 20);
Prefix("some", 10);
Infix("and", 30);
Infix("are", 40);
/// object name in person's inventory is stored in plural unless it's uncountable
Knowledge := {
{"objects", {} },
{"countable objects", {} },
{"persons", {} }
};
/// articles a, an are the same as quantifiers and can be used only with countable objects
10 # (an _x) _(Not IsList(x) And IsCountableObject(PluralFromSingular(x))) <-- {PluralFromSingular(x), 1};
10 # (a _x) _(Not IsList(x) And IsCountableObject(PluralFromSingular(x))) <-- {PluralFromSingular(x), 1};
// "the" with countable
10 # (the _x) _(Not IsList(x) And IsCountableObject(PluralFromSingular(x))) <-- {PluralFromSingular(x), 1};
// "the" with uncountable
20 # (the _x) _(Not IsList(x) And IsSomeObject(x)) <-- {x, 1};
20 # _x is a person <-- DeclarePerson(x);
20 # _x is an object <-- DeclareObject(x);
/// multiple "and" clauses
10 # x_IsList and _y <-- Concat(x, {y});
15 # _x and _y <-- Concat({x}, {y});
/// "some"
some _obj <-- {obj, True};
/// declare many objects or many persons at once
20 # x_IsList are persons <-- MapSingle("DeclarePerson", x);
20 # x_IsList are objects <-- MapSingle("DeclareObject", x);
10 # there are many xs_IsList <-- MapSingle("DeclareCountable", xs);
20 # there are many _xs <-- DeclareCountable(xs);
/// aux function
DeclarePerson(x) :=
// check that hasn't been already declared
If (
IsPerson(x),
Echo({"Note: we already know that ", x, " is a person"}),
[
// store knowledge: person with empty inventory list
Knowledge["persons"][String(x)] := {};
Echo({"OK, ", x, "is a person."});
]
);
/// predicates
IsPerson(x) := Contains(AssocIndices(Knowledge["persons"]), String(x));
/// countable objects are always in plural (IsCountableObject(apple) <-- False if "apples" is defined)
IsCountableObject(x) := Contains(Knowledge["countable objects"], String(x));
/// IsSomeObject(x) means that either x is uncountable, or the plural form of x is countable
IsSomeObject(x) := Contains(Knowledge["objects"], String(x));
/// AssumeIsPerson will always return True and will declare a person if needed
AssumeIsPerson(x) := If(IsPerson(x), True, DeclarePerson(x));
/// declare uncountable object
DeclareObject(x) :=
// check that hasn't been already declared
If (
IsSomeObject(x) Or IsCountableObject(x),
Echo({"Note: we already know that ", x, " is an object"}),
[
// store knowledge: object name
Push(Knowledge["objects"], String(x));
Echo({"OK, ", x, "is an object."});
]
);
DeclareCountable(x) := [
Local(singular);
singular := SingularFromPlural(x);
DeclareObject(singular);
// check that hasn't been already declared
If(
IsCountableObject(x),
Echo({"Note: we already know that there are many ", x}),
[
// store knowledge: countable object
Push(Knowledge["countable objects"], String(x));
MacroRuleBase(String(x), {n});
MacroRule(String(x), 1, 1, True) {x, n};
// Postfix does not evaluate its argument, so need to jump through hoops
Eval(UnList({Postfix, String(x)} ));
Echo({"OK, we assume that the plural of \"", singular, "\" is \"", x, "\"."});
]
);
];
/// get singular forms from plural, e.g. apples->apple
SingularFromPlural(x) := [
Local(singular);
singular := String(x); // cut the ending "s"
singular := StringMid'Get(1, Length(singular)-1, singular);
Atom(singular);
];
/// get plural forms from singular, e.g. apple->apples
PluralFromSingular(x) := [
Local(plural);
plural := ConcatStrings(String(x), "s"); // add the ending "s"
Atom(plural);
];
/// find out how much they have and print an atom as a result
/// note that "x has {list}" is a predicate defined below
/// print number for countable objects and "some" or "no" for uncountable
10 # (_x has _obj)_(Not IsList(obj)) <-- [
Local(quantity);
// defined "quantity" just to save typing
quantity := Knowledge["persons"][String(x)][String(obj)];
If(
IsPerson(x),
If(quantity=0 Or quantity=Empty, no,
If(IsSomeObject(obj), "some", quantity
)
)
, False
);
];
/// predicates to check who has what -- note difference from the above function
10 # _x has {_obj, True} <-- IsPerson(x) And Knowledge["persons"][String(x)][String(obj)] != Empty And Knowledge["persons"][String(x)][String(obj)] > 0;
20 # _x has {_obj, n_IsInteger} <-- IsPerson(x) And Knowledge["persons"][String(x)][String(obj)] = n;
/// limitation: cannot match abstract functions with special syntax, e.g. can't do this:
///10 # (x_IsPerson had _obj(n_IsInteger)) <-- ...;
/// when _obj is supposed to match *any* prefix operator.
/// therefore we shall transform object quantifiers first.
/// "x had N As" parsed into "Serge had {apples, 6}"
10 # (x_AssumeIsPerson had {_obj, n_IsInteger}) _ (IsCountableObject(obj) Or n = 1 And IsSomeObject(obj)) <-- [
// check knowledge: did they have it before? if yes, print warning
If(
x has some obj, // need to check if it is consistent
If(
x has {obj, n},
Echo({"Note: we already know that ", x, " had ", n, " ", obj, " at that time."}),
[
Echo({"Error: we know that ", x," had ", x has obj, " ", obj, " at that time."});
False;
]
),
[
// store knowledge: x now has n obj's
Knowledge["persons"][String(x)][String(obj)] := n;
Synopsis(x, obj);
]
);
];
/// "x ate N As"
10 # (x_AssumeIsPerson ate {_obj, n_IsInteger}) _ (IsCountableObject(obj) Or n = 1 And IsSomeObject(obj)) <--
// check knowledge: did they have it before? if yes, print warning
If(
(x has some obj) And (IsCountableObject(obj) And (x has obj) >= n Or Not IsCountableObject(obj)), // need to check if it is consistent
[
// store knowledge: x now has fewer obj's
Knowledge["persons"][String(x)][String(obj)] := Knowledge["persons"][String(x)][String(obj)] - n;
Synopsis(x, obj);
],
[
Echo({"Error: ", x, " does not have enough ", obj, " at this time."});
False;
]
);
/// aux function to print diagnostic messages
Synopsis(x, obj) := Echo({"OK, ", x, " has ", x has obj, " ", obj, " now."});
/// X ate some A (uncountable only)
20 # (x_AssumeIsPerson ate {_obj, True}) _ (Not IsList(obj) And IsSomeObject(obj)) <--
If(
x has some obj,
Echo({"OK, ", x, " still has some ", obj}),
[
Echo({"Error: ", x, " does not have any ", obj});
False;
]
);
/// X ate A
30 # (x_AssumeIsPerson ate _obj)_ (Not IsList(obj) And IsSomeObject(obj)) <-- x ate {If(IsCountableObject(PluralFromSingular(obj)), PluralFromSingular(obj), obj), 1};
/// interface for "had" in case we are dealing with uncountable objects
/// {obj, True} is a result of "some obj"
20 # (x_AssumeIsPerson had {_obj, True}) _ (Not IsList(obj)) <-- x had {obj, 1};
/// just "obj" means "1 obj" or "1 objs" depending on whether "obj" is countable
30 # (x_AssumeIsPerson had _obj) _ (Not IsList(obj)) <-- x had {If(IsCountableObject(PluralFromSingular(obj)), PluralFromSingular(obj), obj), 1};
/// making new objects
10 # (x_AssumeIsPerson made {_obj, n_IsInteger}) _ (IsCountableObject(obj) Or n = 1 And IsSomeObject(obj)) <-- [
Local(quantity);
quantity := Knowledge["persons"][String(x)][String(obj)];
If(IsNumber(quantity),
quantity := quantity + n,
quantity := n
);
Knowledge["persons"][String(x)][String(obj)] := quantity;
Synopsis(x, obj);
];
/// interface for making "some" new object
20 # (x_AssumeIsPerson made {_obj, True}) _ (Not IsList(obj) And IsSomeObject(obj) And Not IsCountableObject(PluralFromSingular(obj))) <-- x made {obj, 1};
30 # (x_AssumeIsPerson made _obj) _ (Not IsList(obj)) <-- x made {If(IsCountableObject(PluralFromSingular(obj)), PluralFromSingular(obj), obj), 1};
/// giving objects to other people
10 # _x gave _obj to _y <-- [
x ate obj;
y made obj;
];
/// knowledgebase is stored in a global variable Knowledge
/// format: {{"persons", {{"name", {{"objname", quantity}, ...}}, ...} }, {"objects", {"name", ... } }, {"countable objects", {"name", ... } } }
/// print all knowledge
Knowledge() := [
Local(person, object);
Echo("OK, this is what we know:");
WriteString("Persons: ");
WriteString(PrintList(AssocIndices(Knowledge["persons"])));
NewLine();
WriteString("Object names: ");
WriteString(PrintList(Knowledge["objects"]));
NewLine();
WriteString("Countable objects: ");
WriteString(PrintList(Knowledge["countable objects"]));
NewLine();
ForEach(person, AssocIndices(Knowledge["persons"]))
[
Echo({person, " has: "});
ForEach(object, AssocIndices(Knowledge["persons"][person]))
Echo({Atom(person) has Atom(object), Atom(object)});
Echo("");
];
];
/// testing
/*
Jitse and Ayal are persons;
apple is an object;
there are many apples and pears;
Serge had an apple;
Jitse had (10!) pears;
Ayal had (2+3) apples and Serge had 2 pears;
Serge ate the apple;
Ayal ate a pear; // this should fail
Ayal gave an apple to Serge and Serge gave a pear to Ayal;
Ayal ate a pear;
soup is an object and Ayal had some soup;
Ayal gave soup to Serge and Serge ate the soup;
Serge has soup
Serge has apples
Ayal has apples
Serge has some soup
Serge has some apples
Ayal has some pears
Knowledge();
software is an object
Ayal made some software
Ayal gave some software to everyone
Knowledge();
//*/
|