counting number of string occurrences - lua

I'm trying to count the number of times that " --" occurs in a string.
So for instance, it occurs twice here 'a --b --c'
I tried the following, but it gives me 4 instead of 2, any idea why?
argv='a --b --c'
count = 0
for i in string.gfind(argv, " --") do
count = count + 1
end
print(count)

you can actually do this as a one-liner using string.gsub:
local _, count = string.gsub(argv, " %-%-", "")
print(count)
no looping required!
Not recommended for large inputs, because the function returns the processed input to the _ variable, and will hold onto the memory until the variable is destroyed.

This snippet could be helpful, based on response of Mike Corcoran & optimisation suggestion of WD40
function count(base, pattern)
return select(2, string.gsub(base, pattern, ""))
end
print(count('Hello World', 'l'))

The - character has special meaning in patterns, used for a non-greedy repetition.
You need to escape it, i.e. use the pattern " %-%-".

Related

Lua - How to ignore a result from a table iteration without removing it?

I wanto to create a crossword puzzles's solver with Lua. I'm not used to this language tho and my english is poor, sorry for that.
I have to iterate multiples times the same table of tables checking if the given word is present or not and, if present, replace every char of that word in the table with a "*" simbol.
For example:
schema= {
{"A","B","C","D","H","F","G","W","T","Y"},
{"U","H","E","L","L","O","I","I","O","L"},
{"G","F","D","R","Y","T","R","G","R","R"}}
function(schema,"HELLO")
schema= {
{"A","B","C","D","H","F","G","W","T","Y"},
{"U","*","*","*","*","*","I","I","O","L"},
{"G","F","D","R","Y","T","R","G","R","R"}}
For now i'm focusing on find the word scanning the table from left to right. Here's my code:
i = 1
t = {}
for k,w in pairs(schema) do
t[k] = w
end
cercaPrima = function(tabella,stringa)
for v = 1, 10 do
if string.sub(stringa,1,1) == t[i][v] then
print(t[i][v]) v = v+1
return cercaDS(t,stringa,i,v)
else
v = v+1
end
end
if i < #t then
i = i+1
cercaPrima(tabella,stringa)
else
return print("?")
end
end
cercaDS = function(tabella,stringa,d,s)
local o = 2
local l = 2
while o <= #stringa do
if string.sub(stringa,o,l) == tabella[d][s] then
print(tabella[d][s])
tabella[d][s] = "*"
s=s+1
o=o+1
l=l+1
else
l=l-1
s=s-l
o=#stringa+1
tabella[d][s] = "*"
return cercaPrima(tabella,stringa)
end
end
end
cercaPrima(schema,"HELLO")
It's probably overcomplicated, but my question is: How can I make it ignore the first "H" (not turning it into a "*") while keep iterating the table looking for another "H" who fits the criteria?
My goal is to create a function who takes a table and a list of words in input, iterates the table looking for every single word, if it finds them all it replaces every char of every word found in the table with a "*" and print the remaining characters as a string.
Another problem that i'll probabily have is: what if a char of a word is a char of another word too? It will read "*" instead of the real char if it has already found the first word.
Should I create a new table for every word I'm looking for? But then how can i merge those table togheter to extrapolate the remaining characters?
Thank you for your help!
If you want to ignore something one time you can use a conditional statement. Just remember that you encountered it already using a variable. But I don't see how this makes sense here.
A problem like this is probably solved better by turing each line and column into strings and then stimply search the strings for words.
I find string.gsub() is a great find and replacement tool.
Maybe it hit not all requirements but maybe it inspire you.
> function cercaPrisma(tab,txt) for i=1,#tab do print((table.concat(tab[i]):gsub(txt, ('*'):rep(txt:len())))) end end
> cercaPrisma(schema, 'HELLO')
ABCDHFGWTY
U*****IIOL
GFDRYTRGRR
> cercaPrisma(schema, 'DRY')
ABCDHFGWTY
UHELLOIIOL
GF***TRGRR

Neo4J Cypher - SET data ONCE after processing it in a loop

I'm working on a short homomorphic query which aims to transform certain letters of a string input, into other fixed letters.
For instance, I would like all the letters 'A' to be transformed in 'E', and all the 'E' to be turned into 'O'.
I can't use sequentials native replace() functions, because the following would happen:
Input : LEA
replace n°1: LEE
replace n°2: LOO
Wished output versus output obtained : LOE / LOO
So I decided to process letter by letter, looping over my string caracters. In the below example I transform all the 'E' by 'O':
MATCH (...stringToReplace..)
UNWIND range(0,size(apoc.text.split(stringToReplace,'',0))-1) AS i
SET stringToReplace = CASE
WHEN apoc.text.split(stringToReplace,'',0)[i] = 'E'
THEN substring(stringToReplace,0,i) + "O" + substring(stringToReplace, i+1, size(apoc.text.split(stringToReplace,'',0))-1)
ELSE stringToReplace
END
RETURN stringToReplace
The problem I encounter is that I'll have as many SET queries as the string has letters. I think that performance-wise, this is pretty lame.
What I would like to have, and I'm not sure it's possible in Cypher, is to modify an aggregating variable inside the loop and then SET my data. I tried to use a WITH statement before my UNWIND loop but didn't manage to store data inside a var.
Edit: I managed to do a different implementation but it's still return and setting too many times. Even though the end result is right.
MATCH (...stringToReplace...)
UNWIND range(0,size(apoc.text.split(stringToReplace,'',0))-1) AS i
WITH CASE
WHEN apoc.text.split(stringToReplace,'',0)[i] = 'a'
THEN substring(stringToReplace,0,i) + "i" + substring(stringToReplace, i+1, size(apoc.text.split(stringToReplace,'',0))-1)
ELSE stringToReplace
END AS outputString, stringToReplace
SET stringToReplace = outputString
RETURN stringToReplace
This should convert every character in stringToReplace
MATCH (...stringToReplace..)
RETURN REDUCE(s = '', c IN split(stringToReplace,'') |
s + CASE c
WHEN 'A' THEN 'E'
WHEN 'E' THEN 'O'
ELSE c
END
) as result
Just add more WHEN/THEN clauses to handle all the character conversions needed.

How to fix an output error in Python ? It keeps displaying 'None'

I've written a code for 20 Questions Game that should guess the number a user has selected from 1 to 100. But, it keeps displaying the same output again and again which is as given below. Please help me find the error.
The Code is:
a=1
b=10
for i in range(a,101):
y=input(print("Is your number b/w",a,"to",b,"including both ? Answer Yes or No"))
if(y==Yes):
j=a
for j in range(a,b+1):
x=input(print("Is your no.",j,"?"))
if(x==Yes):
print("Your number is",j)
else:
j=j+1
if(y==No):
break
a=a+10
b=b+10
The Output looks like this
Is your number b/w 1 to 10 including both ? Answer Yes or No
None
Take a look at some examples online of how the input function is used and what it takes as a parameter.
The value None you are seeing is the return of the print statement.
input(print("Is your number b/w",a,"to",b,"including both ? Answer Yes or No"))
Should be:
input("Is your number b/w " + str(a) + " to " + str(b) + " including both ? Answer Yes or No")
input accepts a string as a parameter, that gets printed. You passed print as the parameter.
Since print doesn't return anything, hence you get the output as None
Also, unless you have defined Yes and No as variables, they should be enclosed in single or double quotes:
Either this way (not recommended):
Yes = 'Yes'
No = 'No'
....
Or this way(recommended):
if y=='Yes':
....
You need to make changes in this manner for all your input and if statements.

How to refactor string containing variable names into booleans?

I have an SPSS variable containing lines like:
|2|3|4|5|6|7|8|10|11|12|13|14|15|16|18|20|21|22|23|24|25|26|27|28|29|
Every line starts with pipe, and ends with one. I need to refactor it into boolean variables as the following:
var var1 var2 var3 var4 var5
|2|4|5| 0 1 0 1 1
I have tried to do it with a loop like:
loop # = 1 to 72.
compute var# = SUBSTR(var,2#,1).
end loop.
exe.
My code won't work with 2 or more digits long numbers and also it won't place the values into their respective variables, so I've tried nest the char.substr(var,char.rindex(var,'|') + 1) into another loop with no luck because it still won't allow me to recognize the variable number.
How can I do it?
This looks like a nice job for the DO REPEAT command. However the type conversion is somewhat tricky:
DO REPEAT var#i=var1 TO var72
/i=1 TO 72.
COMPUTE var#i = CHAR.INDEX(var,CONCAT("|",LTRIM(STRING(i,F2.0)),"|"))>0).
END REPEAT.
Explanation: Let's go from the inside to the outside:
STRING(value,F2.0) converts the numeric values into a string of two digits (with a leading white space where the number consist of just one digit), e.g. 2 -> " 2".
LTRIM() removes the leading whitespaces, e.g. " 2" -> "2".
CONCAT() concatenates strings. In the above code it adds the "|" before and after the number, e.g. "2" -> "|2|"
CHAR.INDEX(stringvar,searchstring) returns the position at which the searchstring was found. It returns 0 if the searchstring wasn't found.
CHAR.INDEX(stringvar,searchstring)>0 returns a boolean value indicating if the searchstring was found or not.
It's easier to do the manipulations in Python than native SPSS syntax.
You can use SPSSINC TRANS extension for this purpose.
/* Example data*/.
data list free / TextStr (a99).
begin data.
"|2|3|4|5|6|7|8|10|11|12|13|14|15|16|18|20|21|22|23|24|25|26|27|28|29|"
end data.
/* defining function to achieve task */.
begin program.
def runTask(x):
numbers=map(int,filter(None,[i.strip() for i in x.lstrip('|').split("|")]))
answer=[1 if i in numbers else 0 for i in xrange(1,max(numbers)+1)]
return answer
end program.
/* Run job*/.
spssinc trans result = V1 to V30 type=0 /formula "runTask(TextStr)".
exe.

Find the string length of a Lua number?

Easy question here, probably, but searching did not find a similar question.
The # operator finds the length of a string, among other things, great. But with Lua being dynamically typed, thus no conversion operators, how does one type a number as a string in order to determine its length?
For example suppose I want to print the factorials from 1 to 9 in a formatted table.
i,F = 1,1
while i<10 do
print(i.."! == "..string.rep("0",10-#F)..F)
i=i+1
F=F*i
end
error: attempt to get length of global 'F' (a number value)
why not use tostring(F) to convert F to a string?
Alternatively,
length = math.floor(math.log10(number)+1)
Careful though, this will only work where n > 0!
There are probably a dozen ways to do this. The easy way is to use tostring as Dan mentions. You could also concatenate an empty string, e.g. F_str=""..F to get F_str as a string representation. But since you are trying to output a formatted string, use the string.format method to do all the hard work for you:
i,F = 1,1
while i<10 do
print(string.format("%01d! == %010d", i, F))
i=i+1
F=F*i
end
Isn't while tostring(F).len < 10 do useful?

Resources