How i can convert "• Robbery No. 1 occurred on Johnny's person on Tuesday in the park" to prolog rule/fact? - prolog

How i can convert "• Robbery No. 1 occurred on Johnny's person on Tuesday in the park" to prolog rule/fact?

How about:
robbery(1, johnny, tuesday, park).
... as 1 of many ways, depending on how you want to use the info.

Related

Ruby replacing only the first occurrence of multiple regexes passed as a hash

I have a paragraph of text and want to only Ruby sub the first regex match of the word. This would be fine if I only had to match one string, but I'm passing multiple regexes into my sub:
regex = Regexp.new(["Lebron James", "Chris Paul"].join("|"))
names_hash = {"Lebron James" => "**Lebron James**", "Chris Paul" => "**Chris Paul**"}
str = "of the best players left in the playoffs, Lebron James is the most experienced player left in the field and probably in all of the league. Chris Paul has played in many playoff games but has never been to a conference final. Lebron James on the other hand, has been to seven straight NBA finals."
If I run str.gsub(regex, names_hash), all instances of Lebron James and Chris Paul get replaced to:
"of the best players left in the playoffs, Lebron James is the most
experienced player left in the field and probably in all of the
league. Chris Paul has played in many playoff games but has never
been to a conference final. Lebron James on the other hand, has been
to seven straight NBA finals."
And if I run str.sub(regex, names_hash) (sub instead of gsub), I get only the first occurrence of Lebron James, but not Chris Paul:
"of the best players left in the playoffs, Lebron James is the most
experienced player left in the field and probably in all of the
league. Chris Paul has played in many playoff games but has never been
to a conference final. Lebron James on the other hand, has been to
seven straight NBA finals."
My question:
How do I set up what I have so that I can replace both the first instance of Lebron James and Chris Paul, but not the second reference of Lebron James? My expected result:
"of the best players left in the playoffs, Lebron James is the most
experienced player left in the field and probably in all of the
league. Chris Paul has played in many playoff games but has never been
to a conference final. Lebron James on the other hand, has been to
seven straight NBA finals."
How about:
regex = Regexp.new(["Lebron James", "Chris Paul"].join("|"))
names_hash = {"Lebron James" => "**Lebron James**", "Chris Paul" => "**Chris Paul**"}
str = "of the best players left in the playoffs, Lebron James is the most experienced player left in the field and probably in all of the league. Chris Paul has played in many playoff games but has never been to a conference final. Lebron James on the other hand, has been to seven straight NBA finals."
str.gsub(regex) { |name| names_hash.delete(name) || name }
This will read from the names_hash only for the first replacement; after that, the gsub will "default" to making no alteration.
Note that this approach mutates the original names_hash - so you may need to dup it beforehand if the variable is needed later on.
One option would be to call sub separately for each name in sequence.
Alternatively, you can use the block form of gsub to keep track of which names you've already highlighted:
names_seen = []
regex = Regexp.union(["Lebron James", "Chris Paul"])
str = ..
str.gsub(regex) do |name|
if names_seen.include?(name)
name # not the first; replace with itself
else
names_seen << name # remember
"**#{name}**" # or use `names_hash[name]` if needed
end
end
Although Tom Lords answer is good, I want to show you a different way of solving your issue. My solution involves calling String#sub as many times as you have names.
str = 'of the best players left in the playoffs, Lebron James is the most experienced player left in the field and probably in all of the league. Chris Paul has played in many playoff games but has never been to a conference final. Lebron James on the other hand, has been to seven straight NBA finals.'
names = ['Lebron James', 'Chris Paul']
original answer
replacements = names.map { |name| "**#{name}**" }
replacements = names.zip(replacements)
replacements.inject(str) { |str, args| str.sub(*args) }
As mudasobwa pointed out in the comments, the #map / #zip might be overkill. You could just run the following instead:
names.inject(str) { |str, name| str.sub(name, "**#{name}**") }
returns
"of the best players left in the playoffs, Lebron James is the most experienced player left in the field and probably in all of the league. Chris Paul has played in many playoff games but has never been to a conference final. Lebron James on the other hand, has been to seven straight NBA finals."
references
Array#map
Array#zip
Enumerable#inject

How to put information into prolog

> The father sat to the right of the person who had corn,
> who sat to the right of the person who ate pork, who sat to the right of the
> person who had baked potato, who sat to the right of the person who
> had peas.
How this can be converted into Prolog predicates? Can anyone help?
I would first rephrase this as "right to the person who had corn is the father. right to the person who ate pork is the person who had corn." etc. And then use the predicate right(x, y) for "right to x is y". The end result is:
right(corn, father).
right(pork, corn).
right(potato, pork).
right(peas, potato).

Checking List in Prolog

I'm trying to do a schedule that has constraints in Prolog. Scheduling will be based on two constraints. The courses of the same semester and the courses taught by the same instructor cannot be scheduled to the same time slot.
course(ceng123,1).
Course code and semester of course.
slot(monday,1).
Day and hour on day.
teaches(jack,ceng123).
Teacher and course code.
course(cse111,1).
course(cse112,1).
course(cse113,1).
course(cse114,1).
course(cse115,2).
course(cse116,2).
course(cse117,2).
course(cse118,2).
slot(monday,1).
slot(monday,2).
slot(tuesday,1).
slot(tuesday,2).
teaches(erkan,cse111).
teaches(erkan,cse112).
teaches(erkan,cse113).
teaches(erkan,cse114).
teaches(merkan,cse115).
teaches(merkan,cse116).
teaches(kan,cse117).
teaches(kan,cse118).
The answer that I expect is:
?- schedule([cse111,cse112,cse113,cse114,cse115,cse116,cse117,cse118],X).
X = [cse111, monday, 1, cse112, monday, 2, cse113, tuesday, 1, cse114, tuesday, 2, cse115, monday, 1, cse116, monday, 2, cse117, tuesday, 1, cse118, tuesday, 2]
I wrote a code that has no constraints:
course(cse111,1).
course(cse112,1).
course(cse113,1).
course(cse114,1).
course(cse115,2).
course(cse116,2).
course(cse117,2).
course(cse118,2).
slot(monday,1).
slot(monday,2).
slot(tuesday,1).
slot(tuesday,2).
teaches(erkan,cse111).
teaches(erkan,cse112).
teaches(erkan,cse113).
teaches(erkan,cse114).
teaches(merkan,cse115).
teaches(merkan,cse116).
teaches(kan,cse117).
teaches(kan,cse118).
schedule([],[]).
schedule([Course|CourseTail],[Course,Day,Slot|ScheduleTail]):-
slot(Day,Slot),schedule(CourseTail,ScheduleTail).
There is no problem, but when i try this;
course(cse111,1).
course(cse112,1).
course(cse113,1).
course(cse114,1).
course(cse115,2).
course(cse116,2).
course(cse117,2).
course(cse118,2).
slot(monday,1).
slot(monday,2).
slot(tuesday,1).
slot(tuesday,2).
teaches(erkan,cse111).
teaches(erkan,cse112).
teaches(erkan,cse113).
teaches(erkan,cse114).
teaches(merkan,cse115).
teaches(merkan,cse116).
teaches(kan,cse117).
teaches(kan,cse118).
schedule([],[]).
schedule([Course|CourseTail],[Course,Day,Slot|ScheduleTail]):-
schedule(CourseTail,ScheduleTail), check(Course,Day,Slot,ScheduleTail).
check(_, _, _,[]).
check(Course,Day,Slot,[Course2,Day2,Slot2|Tail]):- check(Course,Day,Slot,Tail),
course(Course,Semester1),course(Course2,Semester2),Semester1=\=Semester2,
slot(Day,Slot),slot(Day2,Slot2).
I tried to write constraint but I took an error.
uncaught exception: error(syntax_error('user_input:1 (char:4) . or operator expected after expression'),read_term/3)
Can you see the mistake?
Singleton variable is a variable which is mentioned only once in the program: See wiki. You get that for line 27 which I presume is this one: check(Course,Day,Slot,[]). You can replace it with check(_, _, _,[]). ('_' means any variable. This means you can universally quantify the variables.)
You do not get an error. Prolog saying no just means that your constraints cannot be satisfied.
You should start by clearly defining your constraints.
From your comments, I read:
Two courses in an hour cannot have same semester number and same teacher's courses will not be in same hour.
Therefore you can assign a schedule to a course when it fulfills those requirements, hinting that you have to know which assignments have been already issued. So you can create a procedure that keeps the current schedule and only add a new assignment when your requirements are met.
So, start by defining your schedule/2 procedure that calls a new procedure schedule/3 with an empty list:
schedule(Courses,Schedule):-
schedule(Courses, [], Schedule).
Now, this procedure has on the first argument the list of courses to assign a schedule, keeps the current assignments con the second argument and unifies the third argument with the final Schedule (with the data you require, that is Course, Day and Slot).
I'll use a structure to represent each assignment schedule(Course, Day, Slot) because just mixing those datum in a list is not a good idea.
schedule([], _, []).
schedule([Course|CourseTail], Courses, [schedule(Course,Day,Slot)|ScheduleTail]):-
% Two courses in an hour cannot have same semester number and same teacher's courses will not be in same hour.
course(Course, Semester),
teaches(Teacher, Course),
slot(Day, Slot),
\+ member(s(Day, Slot, Semester, _), Courses),
\+ member(s(Day, Slot, _, Teacher), Courses),
schedule(CourseTail, [s(Day, Slot, Semester, Teacher)|Courses], ScheduleTail).
First clause is the base case. It states that when there are no more courses in the input list, then the schedule will be empty.
Second clause takes the first Course from the input list and computes a possible Semester, Theacher and Day/Slot for that course, and then just checks if the constraints are met. It tests whether there is already a schedule for that Day/Slot/Semester and whether there is already an assignment for the Teacher at that Day/Slot. If the requirements are met then we add this assignment to the list of current assignments and continue recursion.
Upon return, we add the Course/Day/Slot to the list of the final Schedule.

Prolog determinacy - grouping facts

I have a fact set as so...
fav_fruit(male, young, apple).
fav_fruit(female, young, bannana).
fav_fruit(male, old, bannana).
fav_fruit(female, old, apple).
fav_fruit(female, young, apple).
I'm need find out if there is any group of (Gender,Age) where there is more the one favorite fruit (the answer for the facts above would be (female,young.)
What I've been trying to figure out is how to use the aggregate or findall functions in prolog to return some type of list like....
female, young = 2 (apple, bannana)
male, young = 1 (apple)
male, old = 1 (bannana)
female, old = 1 (apple)
...that way I could just check the total for each member and test whether it it greater then 1.
Any ideas would be greatly appreciated.
How about
fav_fruit_class(Gender-Age, List):-
findall(Gender-Age, fav_fruit(Gender, Age, _), LGenderAge),
sort(LGenderAge, SGenderAge),
member(Gender-Age, SGenderAge),
findall(Fruit, fav_fruit(Gender, Age, Fruit), List).
The first findall+sort gets a list of classes (Gender/Age). The second findall gets the list of favorite fruits for each class.

Calculating future occurrences of Friday the 13th

I'd like to be able to start with a year, and calculate occurrences of Friday the 13th. A brute force solution is easy and obvious. I have something slightly better, but I have no doubt that someone else can come up with an elegant algorithm for this.
Perhaps a little trickier, I'd be interested in giving the program a month, and have it find the next year in which that month has a Friday the 13th.
Feel free to use pseudo code, but I expect people will vote more for working code samples in you favorite language.
Any month that starts with a Sunday has a Friday on the thirteenth. There are only 14 combinations possible knowing what day the first of the year is on (with or without leap year, and sun-sat). You should just calculate it once and get it over with. You'd only check 14*12 possible months to start out with, well with in reason.
resultant table element (from 2009, 2010):
[Thursday,false] => Feb, March, Nov
[Friday,false] => Aug
to fill the table you have a generic month Jan(31),Feb(28).. and then iterate with a seed of each day of the week, noting months that start with sunday, and also with a leap year and without. Pretty straight forward, and once done, you can share it with us :)
Since your brute force algorithm is apparently the intuitive day-by-day iteration option, perhaps you haven't considered the Doomsday Algorithm. It would allow you to simply check if that 13th is a Friday. As far as I know, it is the most efficient solution to the problem.
Here's some example PHP code that goes through a pretty straight forward loop of the dates in a range. I would modify this to check the 13th of each month for Fridayness, rather than checking every Friday for 13thness, as they do in the example.
One thing I noticed is that the first of the month falls on a Sunday during months with a Friday the 13th. You can probably leverage this to make it easier to calculate.
initialize startDate to 13th of the month given in the current year
while (true) {
if (startDate.dayOfWeek == Date.FRIDAY)
break;
else
startDate.year ++;
}
return startDate.year;
This is how I would do it:
Assume year is known and is an integer.
Loop from 1 to 12
Create date with loop index, year and 13 for the day
Determine day of week as per established algorithms
If day of week calculated above is Friday, do your work
If you want to start with a month and year (you have to assume some sort of year), your algorithm becomes
Assume year is known and an integer
Assume month is known and is an integer
Loop
Create date with index of loop as year, known month variable, and 13 for the day
Determine day of week as per established algorithms
If day of week calculate above is Friday, return date, else
Else increment year by 1
I use PowerShell 7.1 x64 on Windows 10, I am also interested in this, though my programming skill is not advanced enough to develop an independent and complex algorithm (without built-in) to solve this, currently I can do this:
$start=Read-Host "Input start year"
$end=Read-Host "Input end year"
$years=$start..$end
$blackfriday=#()
foreach ($year in $years) {
$blackfriday+=1..12 | foreach { [datetime]"$year-$_-13" } | where { $_.DayOfWeek -eq 'Friday'} | foreach {$_.tostring("yyyy, MMMM dd, dddd")}
}
$blackfriday
Update:
Now I have this, by brute forcing year-month-13 to convert date to days, and get the results where days mod 7 equal to 5, I have used all the advanced algorithms found on Wikipedia: https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week
And I found out they don't work well with PowerShell, don't know if it's just me or Wikipedia got it wrong, anyway here is my script, I have fc compared the results of the script with builtin and this script, and it shows"FC: no differences encountered":
$months=#(
[PSCustomObject]#{Month='January';Days=31}
[PSCustomObject]#{Month='February';Days=28}
[PSCustomObject]#{Month='March';Days=31}
[PSCustomObject]#{Month='April';Days=30}
[PSCustomObject]#{Month='May';Days=31}
[PSCustomObject]#{Month='June';Days=30}
[PSCustomObject]#{Month='July';Days=31}
[PSCustomObject]#{Month='August';Days=31}
[PSCustomObject]#{Month='September';Days=30}
[PSCustomObject]#{Month='October';Days=31}
[PSCustomObject]#{Month='November';Days=30}
[PSCustomObject]#{Month='December';Days=31}
)
function BlackFriday {
param(
[Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=0)] [int64] $start,
[Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=1)] [int64] $end
)
$years=$start..$end
$blackfriday=#()
foreach ($year in $years) {
$array=1..12
foreach ($arra in $array) {
$month=0
for ($i=0;$i -lt $arra-1;$i++) {
$month+=$months[$i].Days
}
[int]$ye=$year
if ($arra -le 2) { $ye-=1}
if ($ye % 4 -eq 0) {$leap=$ye/4}
else {while ($ye % 4 -ne 0) {$ye-=1}
$leap=$ye/4}
if ($ye % 100 -eq 0) {$century=$ye/100}
else {while ($ye % 100 -ne 0) {$ye-=4}
$century=$ye/100}
if ($ye % 400 -eq 0) {$cycle=$ye/400}
else {while ($ye % 400 -ne 0) {$ye-=100}
$cycle=$ye/400}
$leap=$leap-$century+$cycle
$date=[int64](($year-1)*365+$month+13+$leap)
if ($date % 7 -eq 5) {
$name=$months[$arra-1].Month
$blackfriday+=[string]"$year, $name 13, Friday"
}
}
}
$blackfriday
}
$start=Read-Host "Input start year"
$end=Read-Host "Input end year"
BlackFriday $start $end

Resources