The mystery is finally solved! Yes, the code works.
#!/usr/bin/env swipl --quiet
:- use_module(library(clpfd)).
% ORIGINAL LYRICS:
% Looking for
% Girls who want boys
% Who like boys to be girls
% Who do boys like they're girls
% Who do girls like they're boys
% Always should be someone you really love
% - "Girls and Boys," Blur, 1994
% DSL CONVERSION:
% girls who like boys
% who like boys (who are girls)
% who like boys (who get done like they're girls)
% who like girls (who get done like they're boys)
% TREE STRUCTURE:
% group(female, none, none, group(
% male, female, none, group(
% male, none, female, group(
% female, none, male, none)))).
% USAGE:
% 1. Get all possible lyrics up to a max depth:
% ?- group_maxdepth(G, 4), group_string(G, S).
% 2. Get the tree structure of some lyrics (pass a max depth to avoid unbounded recursion):
% ?- group_maxdepth(G, 4), group_string(G, 'boys who like girls').
% 3. Get the lyrics from a tree structure:
% ?- group_string(group(male, none, none, group(female, none, none, none)), S).
% 4. Fill in the blanks with all possibilities:
% ?- group_depth(G, 3),
% phrase(group_sentence(G), Tokens),
% append([[girls, who, like], X, [who, like], Y], Tokens),
% atomic_list_concat(Tokens, ' ', S).
% Genders
gender(male).
gender(female).
% gender_altgender(G, G2)
% Valid relation between gender and alternative genders (isGender and
% PerformGender) in the same group.
gender_altgender(G, none) :-
gender(G).
gender_altgender(G, G2) :-
gender(G),
gender(G2),
dif(G, G2).
% Group(Gender, IsGender, PerformGender, LikeGroup).
% All arguments but Gender are optional.
% Represents a demographic that can like and can be a target of liking.
group(Gender, IsGender, PerformGender, none) :-
gender(Gender),
gender_altgender(Gender, IsGender),
gender_altgender(Gender, PerformGender).
group(Gender, IsGender, PerformGender, group(Gender2, IsGender2, PerformGender2, Group)) :-
group(Gender, IsGender, PerformGender, none),
group(Gender2, IsGender2, PerformGender2, Group).
% DCG to produce a phrase from a group.
% Example:
% ?- phrase(group_sentence(group(male, none, none, group(female, none, none, group(male, none, none, group(male))))), Tokens).
% Tokens = [boys, who, like, girls, who, like, boys, who, like, boys].
group_sentence(group(Gender, IsGender, PerformGender, none)) -->
{ group(Gender, IsGender, PerformGender, none) },
gender_phrase(Gender),
group_info_phrase(IsGender, PerformGender).
group_sentence(group(Gender, IsGender, PerformGender, Group)) -->
{ dif(Group, none) },
group_sentence(group(Gender, IsGender, PerformGender, none)),
[who, like],
group_sentence(Group).
gender_phrase(male) --> [boys].
gender_phrase(female) --> [girls].
isgender_phrase(none) --> [].
isgender_phrase(Gender) --> [are], gender_phrase(Gender).
performgender_phrase(none) --> [].
performgender_phrase(Gender) --> [get, done, like, 'they''re'], gender_phrase(Gender).
% Render isGender and PerformGender within parentheses.
group_info_phrase(none, none) --> [].
group_info_phrase(IsGender, none) -->
{ dif(IsGender, none) },
['(', who], isgender_phrase(IsGender), [')'].
group_info_phrase(none, PerformGender) -->
{ dif(PerformGender, none) },
['(', who], performgender_phrase(PerformGender), [')'].
group_info_phrase(IsGender, PerformGender) -->
{ dif(IsGender, none), dif(PerformGender, none) },
['(', who], isgender_phrase(IsGender), ['and'], performgender_phrase(PerformGender), [')'].
% Relate group and string representation
% ?- group_string(group(male, none, none, group(female, none, none, group(male, none, none, group(male)))), S).
% S = 'boys who like girls who like boys who like boys'
group_string(group(Gender, IsGender, PerformGender, Group), String) :-
phrase(group_sentence(group(Gender, IsGender, PerformGender, Group)), Tokens),
atomic_list_concat(Tokens, ' ', String).
% Relate group and depth
% - group(G0, IG, PG, none) has depth 0
% - group(G0, IG, PG, group(...)) has depth 1
group_depth(group(Gender, IsGender, PerformGender, none), 0) :-
group(Gender, IsGender, PerformGender, none).
group_depth(group(Gender, IsGender, PerformGender, Group), Depth) :-
Depth #> 0,
group(Gender, IsGender, PerformGender, none),
Depth0 #= Depth - 1,
group_depth(Group, Depth0).
% Relate group and all integers larger than its depth.
group_maxdepth(Group, MaxDepth) :-
MaxDepth #>= Depth,
Depth #>= 0,
group_depth(Group, Depth).
You must log in or register to comment.
Pretty sure the lyrics are:
Girls who are boys
Who like boys to be girls
Who do boys like they’re girls
Who do girls like they’re boysWhich basically means girls taking the stereotypical male role during intercourse while the boys take the stereotypical female role.
Basically “Pegging: The Musical”.
what is #>= operator?
This is a nice overview: CLPFD and CLPZ: Prolog Integer Arithmetic
https://www.swi-prolog.org/pldoc/doc_for?object=%23>%3D+%2F+2
It’s a better replacement for the built-in
=
predicate.
Incredible. I don’t know enough Prolog to be able to follow it very well, but this is truly what the internet was made for
Finally! This has been a major roadblock for the team for a while.