Sierpinski Carpet in Prolog - recursion

Saw this problem here and since I am a prolog newbie, I tried formulating a solution unsuccesfully. Here's what I have managed to make of this so far:
rewrite('X', [['X','X','X'],['X',' ','X'],['X','X','X']]).
rewrite(' ', [[' ',' ',' '],[' ',' ',' '],[' ',' ',' ']]).
rec(1, [], CurrentList, [CurrentList]).
rec(_, [], CurrentList, CurrentList).
rec(0, L, CurrentList, Result):- append(CurrentList, [L], Result).
rec(N, [H|T], CurrentList, Result):-
atom(H),
N > 0,
rewrite(H, L),
K is N - 1,
rec(K, L, CurrentList, Temp),
rec(N, T, Temp, Result).
rec(N, [H|T], CurrentList, Result):-
N > 0,
rec(N, H, CurrentList, Temp),
rec(N, T, Temp, Result).
carpet(N):-
N > 0,
rewrite(Item, _),!,
rec(N, [[Item]], [], Result),
write(Result).
Essentially, I try to expand my first element and then expand each element created by the previous expansion.
Then I wrote the first rec fact that basically is there to place all expanded elements of the previous to last expansion in a list and signal where the newline will be placed but places parentheses from the start to the end of the next expanded group rather than from the start of the next expanded group to it's end.
I might have a lot of faulty logic so any other way to solve this problem would be welcome.

You are not doing yourself a favor by using rec as a predicate name. What is it supposed to do?
Here is my approach. It is based on simplifying the problem first, to only considering one level of rewriting of one non-empty row of symbols. Considering several rows is then simple by iterating that.
% expand_row(Row, Expansion): Row is a list of symbols representing one row
% of the Sierpinski carpet. Expansion is a list of rows, i.e., a list of
% lists of symbols, resulting from rewriting each symbol in Row.
expand_row([C], Expansion) :-
rewrite(C, Expansion).
expand_row([C,D|Cs], Expansion) :-
rewrite(C, ExpansionC),
expand_row([D|Cs], ExpansionRest),
maplist(append, ExpansionC, ExpansionRest, Expansion).
carpet_(1, [['X']]).
carpet_(N, Carpet) :-
N > 1,
N1 is N - 1,
carpet_(N1, Carpet1),
maplist(expand_row, Carpet1, CarpetExpanded),
% remove one level of nesting
append(CarpetExpanded, Carpet).
Note that this only computes the carpet, it doesn't print it. That's better done separately:
write_row(Row) :-
maplist(write, Row),
nl.
write_carpet(Carpet) :-
maplist(write_row, Carpet).
carpet(N) :-
carpet_(N, Carpet),
write_carpet(Carpet).
Test:
?- between(1, 4, N), carpet(N).
X
N = 1 ;
XXX
X X
XXX
N = 2 ;
XXXXXXXXX
X XX XX X
XXXXXXXXX
XXX XXX
X X X X
XXX XXX
XXXXXXXXX
X XX XX X
XXXXXXXXX
N = 3 ;
XXXXXXXXXXXXXXXXXXXXXXXXXXX
X XX XX XX XX XX XX XX XX X
XXXXXXXXXXXXXXXXXXXXXXXXXXX
XXX XXXXXX XXXXXX XXX
X X X XX X X XX X X X
XXX XXXXXX XXXXXX XXX
XXXXXXXXXXXXXXXXXXXXXXXXXXX
X XX XX XX XX XX XX XX XX X
XXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXX XXXXXXXXX
X XX XX X X XX XX X
XXXXXXXXX XXXXXXXXX
XXX XXX XXX XXX
X X X X X X X X
XXX XXX XXX XXX
XXXXXXXXX XXXXXXXXX
X XX XX X X XX XX X
XXXXXXXXX XXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXX
X XX XX XX XX XX XX XX XX X
XXXXXXXXXXXXXXXXXXXXXXXXXXX
XXX XXXXXX XXXXXX XXX
X X X XX X X XX X X X
XXX XXXXXX XXXXXX XXX
XXXXXXXXXXXXXXXXXXXXXXXXXXX
X XX XX XX XX XX XX XX XX X
XXXXXXXXXXXXXXXXXXXXXXXXXXX
N = 4 ;
false.

Related

Shift alphabetical characters in string

Let's say I have a string:
s <- 'hello world zzz'
I want to shift the alphabetical characters up by one.
So:
a becomes b
b becomes c
c becomes d
d becomes e
and so on...
w becomes x
x becomes y
y becomes z
And:
z becomes a
The other condition is that if there is character that isn't in the alphabet (in this case the space), keep the characters as it is, so the space remains as a space.
Would all this be possible?
My desired output here would be:
ifmmp xpsme aaa
I have tried:
new <- c()
for (i in s)
{
new <- c(new, 'abcdefghijklmnopqrstuvwxyz'[which('abcdefghijklmnopqrstuvwxyz' == i) + 1])
}
print(new)
But it doesn't work... It outputs nothing.
Any ways of doing this?
chartr("abcdefghijklmnopqrstuvwxyz", "bcdefghijklmnopqrstuvwxyza", 'hello world zzz')
# [1] "ifmmp xpsme aaa"
(A function I've never had cause to use ...)

How to replace string from numeric value in R?

I have a dataset that contains the number of app installers, the data recorded with units M and K, like: 19M, 199K.
How to replace the prefixes with their values to convert values to numeric.
k to e+3
M to e+6
Edit: For values that have non-integer values.
x <- c("19M","20K","1K", "1.25M", "1.5K"); x
x <- sub("M", "e6", x); x
x <- sub("K", "e3", x); x
as.numeric(x)
[1] 19000000 20000 1000 1250000 1500
For integer values, the following is sufficient.
x <- c("19M","20K","1K")
x <- sub("M","000000", x)
x <- sub("K","000", x)
as.numeric(x)
1.9e+07 2.0e+04 1.0e+03

Randomise across columns for half a dataset

I have a data set for MMA bouts.
The structure currently is
Fighter 1, Fighter 2, Winner
x y x
x y x
x y x
x y x
x y x
My problem is that Fighter 1 = Winner so my model will be trained that fighter 1 always wins, which is a problem.
I need to be able to randomly swap Fighter 1 and Fighter 2 for half the data set in order to have the winner represented equally.
Ideally i would have this
Fighter 1, Fighter 2, Winner
x y x
y x x
x y y
y x x
x y y
is there a way to randomise across columns without messing up the order of the rows ??
I'm assuming your xs and ys are arbitrary and just placeholders. I'll further assume that you need the Winner column to stay the same, you just need that the winner not always be in the first column.
Sample data:
set.seed(42)
x <- data.frame(
F1 = sample(letters, size = 5),
F2 = sample(LETTERS, size = 5),
stringsAsFactors = FALSE
)
x$W <- x$F1
x
# F1 F2 W
# 1 x N x
# 2 z S z
# 3 g D g
# 4 t P t
# 5 o W o
Choose some rows to change, randomly:
(ind <- sample(nrow(x), size = ceiling(nrow(x)/2)))
# [1] 3 5 4
This means that we expect rows 3-5 to change.
Now the random changes:
within(x, { tmp <- F1[ind]; F1[ind] = F2[ind]; F2[ind] = tmp; rm(tmp); })
# F1 F2 W
# 1 x N x
# 2 z S z
# 3 D g g
# 4 P t t
# 5 W o o
Rows 1-2 still show the F1 as the Winner, and rows 3-5 show F2 as the Winner.
I also found that this code worked
matches_clean[, c("fighter1", "fighter2")] <- lapply(matches_clean[, c("fighter1", "fighter2")], as.character)
changeInd <- !!((match(matches_clean$fighter1, levels(as.factor(matches_clean$fighter1))) -
match(matches_clean$fighter2, levels(as.factor(matches_clean$fighter2)))) %% 2)
matches_clean[changeInd, c("fighter1", "fighter2")] <- matches_clean[changeInd, c("fighter2", "fighter1")]

Simplifying this boolean algebra

Is it possible to simplify this boolean algebra? I want to remove the redundancy of using twice the X variable, but can't seem to see a way how.
(X AND Y) OR NOT(X AND Z)
Thanks in advance!
It's equivalent to
(X AND Y) OR (NOT X OR NOT Z)
which is equivalent to
(X AND Y) OR NOT X OR NOT Z
which is equivalent to
(X OR NOT X OR NOT Z) AND (Y OR NOT X OR NOT Z)
which is equivalent to
(TRUE) AND (Y OR NOT X OR NOT Z)
(since X or NOT x == true and TRUE OR Z == true)
which is equivalent to
Y OR NOT X OR NOT Z
You can also use a K-map to find an equivalent logical expression, but those are harder to type :)
This is equal to !(X and !Y and Z).
You could also have the formula
(!X or Y or !Z)
You could confirm the answers in http://www.wolframalpha.com/input/?i=%28X+AND+Y%29+OR+NOT%28X+AND+Z%29
In the Karnaugh map, you can see that your expression is indeed equivalent to a sum of three single-literal terms:
not x or y or not z
yz
00 01 11 10
+---+---+---+---+
0 | 1 | 1 | 1 | 1 |
x +---+---+---+---+
1 | 1 | 0 | 1 | 1 |
+---+---+---+---+
As pointed out by Elye, the single 0 can be expressed as an inverted term with three inputs:
not (x and not y and z)

Remove white space from ff_object in R

I have an ff object. One of the columns, which is a string variable, has white spaces, and I want to remove these.
I have tried the following:
1). newcol <- gsub("[[:space:]]", "", mydata$mystr)
2). newcol<- as.ffdf(gsub("[[:space:]]", "", mydata$mystr))
I also tried to use the as.character command, such that I said the following before applying the gsub command:
mydata$mystr <- as.character(ff(c(mydata$mystr)))
However, none of these options works. Any suggestions/help would be greatly appreciated.
EDIT: SOLUTION GIVEN MY AKRUN BELOW
May be you can try with ffbase
library(ffbase)
library(ff)
head(ffd$y[])
#[1] p l k a i v
#20 Levels: a c c e f h i j k k l l n
#n o ... v
ffd$y <- with(ffd, gsub('[[:space:]]', '', y))
head(ffd$y[])
#[1] p l k a i v
#Levels: a c e f h i j k l n o p q t v
data
set.seed(24)
d <- data.frame(x=1:26, y=sample(c(letters, paste(' ', letters, ' ')),
26, replace=TRUE), z=Sys.time()+1:26)
ffd <- as.ffdf(d)

Resources