How to check for substrings - string

a="hello"
b="hi"
io.write("enter a or b or both:")
c=io.read()
if c=="hello" then
print(b)
elseif c=="hi" then
print (a)
elseif c~=a or b then
print ("unknown word")
end
The problem is when I write both : hello hi, it is showing :unknown word.
How can I fix this?
I also tried with table something like d={},d.a="hello",d.b="hi" but the same problem.

== is used to test equality. But the string "hello hi" is neither equal to "hello" nor "hi". To test if it contains a substring, use pattern matching:
local found = false
if c:match("hello") then
print(a)
found = true
end
if c:match("hi") then
print(b)
found = true
end
if not found then
print ("unknown word")
end

If you want to compare words instead of substrings, try this:
function normalize(x)
return " "..x.." "
end
mywords=normalize("hello hi")
function ok(x)
return mywords:match(normalize(x))~=nil
end
print(ok("hello"))
print(ok("hi"))
print(ok("high"))

Related

Finding the "difference" between two string texts (Lua example)

I'm trying to find the difference in text between two string values in Lua, and I'm just not quite sure how to do this effectively. I'm not very experienced in working with string patterns, and I'm sure that's my downfall on this one. Here's an example:
-- Original text
local text1 = "hello there"
-- Changed text
local text2 = "hello.there"
-- Finding the alteration of original text with some "pattern"
print(text2:match("pattern"))
In the example above, I'd want to output the text ".", since that's the difference between the two texts. Same goes for cases where the difference could be sensitive to a string pattern, like this:
local text1 = "hello there"
local text2 = "hello()there"
print(text2:match("pattern"))
In this example, I'd want to print "(" since at that point the new string is no longer consistent with the old one.
If anyone has any insight on this, I'd really appreciate it. Sorry I couldn't give more to work with code-wise, I'm just not sure where to begin.
Just iterate over the strings and find when they don't match.
function StringDifference(str1,str2)
for i = 1,#str1 do --Loop over strings
if str1:sub(i,i) ~= str2:sub(i,i) then --If that character is not equal to it's counterpart
return i --Return that index
end
end
return #str1+1 --Return the index after where the shorter one ends as fallback.
end
print(StringDifference("hello there", "hello.there"))
local function get_inserted_text(old, new)
local prv = {}
for o = 0, #old do
prv[o] = ""
end
for n = 1, #new do
local nxt = {[0] = new:sub(1, n)}
local nn = new:sub(n, n)
for o = 1, #old do
local result
if nn == old:sub(o, o) then
result = prv[o-1]
else
result = prv[o]..nn
if #nxt[o-1] <= #result then
result = nxt[o-1]
end
end
nxt[o] = result
end
prv = nxt
end
return prv[#old]
end
Usage:
print(get_inserted_text("hello there", "hello.there")) --> .
print(get_inserted_text("hello there", "hello()there")) --> ()
print(get_inserted_text("hello there", "hello htere")) --> h
print(get_inserted_text("hello there", "heLlloU theAre")) --> LUA

Split String and Include Delimiter in Lua

I searched on Google and on Stack Overflow and didn't find answer for this question. Looking at the documentation I didn't find how to do this because every function that allows splits excludes the delimiter.
EDIT
for i, word in pairs(split(text, "<(.-)>")) do
print(word)
end
function split(string, delimiter) -- Got this function from https://helloacm.com/split-a-string-in-lua/
result = {};
for match in (string..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
This code replaces the parts in the format "<(.-)>"
Example:
Input: "Hello<a>World</a>!"
Expected Output: {"Hello", "<a>", "World", "</a>", "!"}
Real Output: {"Hello", "World", "!"}
s = "Hello<a>World</a>!"
for a in s:gsub('%b<>','\0%0\0'):gmatch'%Z+' do
print(a)
end
I assume this is related to HTML tags or similar.
One quick-n-dirty possibility I can think of that should cover your specific use case is this:
s = 'Hello<a>World</a>!'
function split(s)
local ans = {}
for a,b in (s..'<>'):gmatch '(.-)(%b<>)' do
ans[#ans+1] = a
ans[#ans+1] = b
end
ans[#ans] = nil
return ans
end
for _,v in ipairs(split(s)) do
print(v)
end

Getting the largest and smallest word at a string

when I run this codes the output is (" "," "),however it should be ("I","love")!!!, and there is no errors . what should I do to fix it ??
sen="I love dogs"
function Longest_word(sen)
x=" "
maxw=" "
minw=" "
minl=1
maxl=length(sen)
p=0
for i=1:length(sen)
if(sen[i]!=" ")
x=[x[1]...,sen[i]...]
else
p=length(x)
if p<min1
minl=p
minw=x
end
if p>maxl
maxl=p
maxw=x
end
x=" "
end
end
return minw,maxw
end
As #David mentioned, another and may be better solution can be achieved by using split function:
function longest_word(sentence)
sp=split(sentence)
len=map(length,sp)
return (sp[indmin(len)],sp[indmax(len)])
end
The idea of your code is good, but there are a few mistakes.
You can see what's going wrong by debugging a bit. The easiest way to do this is with #show, which prints out the value of variables. When code doesn't work like you expect, this is the first thing to do -- just ask it what it's doing by printing everything out!
E.g. if you put
if(sen[i]!=" ")
x=[x[1]...,sen[i]...]
#show x
and run the function with
Longest_word("I love dogs")
you will see that it is not doing what you want it to do, which (I believe) is add the ith letter to the string x.
Note that the ith letter accessed like sen[i] is a character not a string.
You can try converting it to a string with
string(sen[i])
but this gives a Unicode string, not an ASCII string, in recent versions of Julia.
In fact, it would be better not to iterate over the string using
for i in 1:length(sen)
but iterate over the characters in the string (which will also work if the string is Unicode):
for c in sen
Then you can initialise the string x as
x = UTF8String("")
and update it with
x = string(x, c)
Try out some of these possibilities and see if they help.
Also, you have maxl and minl defined wrong initially -- they should be the other way round. Also, the names of the variables are not very helpful for understanding what should happen. And the strings should be initialised to empty strings, "", not a string with a space, " ".
#daycaster is correct that there seems to be a min1 that should be minl.
However, in fact there is an easier way to solve the problem, using the split function, which divides a string into words.
Let us know if you still have a problem.
Here is a working version following your idea:
function longest_word(sentence)
x = UTF8String("")
maxw = ""
minw = ""
maxl = 0 # counterintuitive! start the "wrong" way round
minl = length(sentence)
for i in 1:length(sentence) # or: for c in sentence
if sentence[i] != ' ' # or: if c != ' '
x = string(x, sentence[i]) # or: x = string(x, c)
else
p = length(x)
if p < minl
minl = p
minw = x
end
if p > maxl
maxl = p
maxw = x
end
x = ""
end
end
return minw, maxw
end
Note that this function does not work if the longest word is at the end of the string. How could you modify it for this case?

String Manipulation in Lua: Make the odd char uppercase

I'm trying to do a library in Lua with some function that manipulate strings.
I want to do a function that changes the letter case to upper only on odd characters of the word.
This is an example:
Input: This LIBRARY should work with any string!
Result: ThIs LiBrArY ShOuLd WoRk WiTh AnY StRiNg!
I tried with the "gsub" function but i found it really difficult to use.
This almost works:
original = "This LIBRARY should work with any string!"
print(original:gsub("(.)(.)",function (x,y) return x:upper()..y end))
It fails when the string has odd length and the last char is a letter, as in
original = "This LIBRARY should work with any strings"
I'll leave that case as an exercise.
First, split the string into an array of words:
local original = "This LIBRARY should work with any string!"
local words = {}
for v in original:gmatch("%w+") do
words[#words + 1] = v
end
Then, make a function to turn words like expected, odd characters to upper, even characters to lower:
function changeCase(str)
local u = ""
for i = 1, #str do
if i % 2 == 1 then
u = u .. string.upper(str:sub(i, i))
else
u = u .. string.lower(str:sub(i, i))
end
end
return u
end
Using the function to modify every words:
for i,v in ipairs(words) do
words[i] = changeCase(v)
end
Finally, using table.concat to concatenate to one string:
local result = table.concat(words, " ")
print(result)
-- Output: ThIs LiBrArY ShOuLd WoRk WiTh AnY StRiNg
Since I am coding mostly in Haskell lately, functional-ish solution comes to mind:
local function head(str) return str[1] end
local function tail(str) return substr(str, 2) end
local function helper(str, c)
if #str == 0 then
return ""
end
if c % 2 == 1 then
return toupper(head(str)) .. helper(tail(str),c+1)
else
return head(str) .. helper(tail(str), c+1)
end
end
function foo(str)
return helper(str, 1)
end
Disclaimer: Not tested, just showing the idea.
And now for real, you can treat a string like a list of characters with random-access with reference semantics on []. Simple for loop with index should do the trick just fine.

Lua - Removing words that are not in a list

i want to remove words that are not in a list, from a string.
for example i have the string "i like pie and cake" or "pie and cake is good" and i want to remove words that are not "pie" or "cake" and end out with a string saying "pie cake".
it would be great, if the words it does not delete could be loaded from a table.
Here's another solution, but you may need to trim the last space in the result.
acceptable = { "pie", "cake" }
for k,v in ipairs(acceptable) do acceptable[v]=v.." " end
setmetatable(acceptable,{__index= function () return "" end})
function strip(s,t)
s=s.." "
print('"'..s:gsub("(%a+) %s*",t)..'"')
end
strip("i like pie and cake",acceptable)
strip("pie and cake is good",acceptable)
gsub is the key point here. There are other variations using gsub and a function, instead of setting a metatable for acceptable.
local function stripwords(inputstring, inputtable)
local retstring = {}
local itemno = 1;
for w in string.gmatch(inputstring, "%a+") do
if inputtable[w] then
retstring[itemno] = w
itemno = itemno + 1
end
end
return table.concat(retstring, " ")
end
Provided that the words you want to keep are all keys of the inputtable.
The following also implements the last part of the request (I hope):
it would be great, if the words it does not delete could be loaded from a table.
function stripwords(str, words)
local w = {};
return str:gsub("([^%s.,!?]+)%s*", function(word)
if words[word] then return "" end
w[#w+1] = word
end), w;
end
Keep in mind that the pattern matcher of Lua is not compatible with multibyte strings. This is why I used the pattern above. If you don't care about multibyte strings, you can use something like "(%a+)%s". In that case I would also run the words through string.upper
Tests / Usage
local blacklist = { some = true, are = true, less = true, politics = true }
print((stripwords("There are some nasty words in here!", blacklist)))
local r, t = stripwords("some more are in politics here!", blacklist);
print(r);
for k,v in pairs(t) do
print(k, v);
end

Resources