Lua - gmatch scientific notation string to number - string

I am trying to convert a string of scientific notation numbers into actual numbers.
My test string is formatted like so:
myString = 1.000000000000000E+00, 2.000000000000000E+02, -1.000000000000000E+05
My current code:
elements = {}
for s in myString:gmatch('%d+%.?%d*') do
table.insert(elements, s);
end
return unpack(elements);
Elements returns the following incorrectly:
1.000000000000000 %from the first number before "E"
00 %after the "E" in the first number
2.000000000000000 %from the second number before "E"
Anyone know how I can go about fixing this?

To me, "actual numbers" means the number data type. tonumber() does quite well with scientific notation.
local myString = [[ 1.000000000000000E+00,
2.000000000000000E+02, -1.000000000000000E+05 ]]
local function convert(csv)
local list = {}
for value in (csv .. ","):gmatch("(%S+)%W*,") do table.insert(list,tonumber(value)) end
return unpack(list)
end
print(convert(myString))

Try this instead:
for s in (myString..","):gmatch("(%S+),") do print(s) end

I would suggest using the gsplit function defined here: SplitJoin, and then having a loop like so:
t = {}
for number in gsplit(myString:gsub('%s',''),',') do
t[#t+1] = tonumber(number)
end
Which for a string:
myString = [[1.000000000000000E+00, 2.000000000000000E+02, -1.000000000000000E+05]]
the result of table.concat(t,',') is:
1,200,-100000

Here is another answer, which is robust but probably overkill:
f = loadstring("return {" .. myString .."}")
if f==nil then end -- myString malformed
elements = f()

Extend the pattern to recognize optional mantissa and use tonumber to get the number from the string:
elements = {}
myString = "1.000000000000000E+00, 2.000000000000000E+02, -1.000000000000000E+05"
for s in myString:gmatch('[+%-]?%d+%.?%d*[eE+%-]*%d?%d?') do
table.insert(elements, tonumber(s))
end
print(unpack(elements))

Related

Converting letters into NATO alphabet in MATLAB

I want to write a code in MATLAB that converts a letter into NATO alphabet. Such as the word 'hello' would be re-written as Hotel-Echo-Lima-Lima-Oscar. I have been having some trouble with the code. So far I have the following:
function natoText = textToNato(plaintext)
plaintext = lower(plaintext);
r = zeros(1, length(plaintext))
%Define my NATO alphabet
natalph = ["Alpha","Bravo","Charlie","Delta","Echo","Foxtrot","Golf", ...
"Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar", ...
"Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor",...
"Whiskey","Xray","Yankee","Zulu"];
%Define the normal lower alphabet
noralpha = ['a' : 'z'];
%Now we need to make a loop for matlab to check for each letter
for i = 1:length(text)
for j = 1:26
n = r(i) == natalph(j);
if noralpha(j) == text(i) : n
else r(i) = r(i)
natoText = ''
end
end
end
for v = 1:length(plaintext)
natoText = natoText + r(v) + ''
natoText = natoText(:,-1)
end
end
I know the above code is a mess and I am a bit in doubt what really I have been doing. Is there anyone who knows a better way of doing this? Can I modify the above code so that it works?
It is because now when I run the code, I am getting an empty plot, which I don't know why because I have not asked for a plot in any lines.
You can actually do your conversion in one line. Given your string array natalph:
plaintext = 'hello'; % Your input; could also be "hello"
natoText = strjoin(natalph(char(lower(plaintext))-96), '-');
And the result:
natoText =
string
"Hotel-Echo-Lima-Lima-Oscar"
This uses a trick that character arrays can be treated as numeric arrays of their ASCII equivalent values. The code char(lower(plaintext))-96 converts plaintext to lowercase, then to a character array (if it isn't already) and implicitly converts it to a numeric vector of ASCII values by subtracting 96. Since 'a' is equal to 97, this creates an index vector containing the values 1 ('a') through 26 ('z'). This is used to index the string array natalph, and these are then joined together with hyphens.

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?

How to tangle/scramble/rearrange a string in MATLAB?

For an example exam question, I've been asked to "tangle" a string as shown:
tangledWord('today')='otady'
tangledWord('12345678')='21436587'
I understand this is an extremely simple problem but it's got me stumped.
I can make it produce a tangled word when the length is even, but I'm having trouble when it's odd, here's my function:
function tangledWord(s)
n=length(s);
a=s(1:2:n);
b=s(2:2:n);
s(1:2:n)=b;
s(2:2:n)=a;
disp(s);
end
For odd word length, you need to reduce n by 1 to leave the last char untouched. Use mod to detect odd word length.
If you want to scramble every char randomly, you can try:
string = '1234567';
shuffled = string(randperm(numel(string)))
shuffled = 5741326
If you want to change the first two chars:
tangled = [string(2) string(1) string(3:end)]
tangled = 2134567
If you want to change every two chars:
n = ( numel(string)-mod(numel(string),2));
tangled2 = [flipud(reshape(string(1:n),[],n/2))(:); string(n+1:end)]'
tangled2 = 2143657
function tangledWord(s)
n=length(s);
if mod(n,2) == 0
a=s(1:2:n);
b=s(2:2:n);
s(1:2:n)=b;
s(2:2:n)=a;
disp(s)
elseif mod(n,2) ~= 0
a=s(1:2:end-1);
b=s(2:2:end-1);
s(1:2:end-1)=b;
s(2:2:end-1)=a;
disp(s)
end
end

How to concatenate strings into one using loop?

can someone help me with string concatenate problem. I read data from register. It's function utf(regAddr, length). I get table with decimal numbers, then I transform it into hex and to string in loop. I need concatenate these strings into one.
there is not in Lua something like .= operator
function utf(regAddr, length)
stringTable = {}
table.insert(stringTable, {mb:readregisters(regAddr-1,length)})
for key, value in pairs(stringTable) do
for i=1, length do
v = value[i]
v = lmcore.inttohex(v, 4)
v = cnv.hextostr(v)
log(v)
end
end
end
-- function(regAddr, length)
utf(30,20)
There is no append operator for strings. Strings are immutable values.
The .. operator concatenates two string, producing a third string as a result:
local b = "con"
local c = "catenate"
local a = b .. c -- "concatenate"
The table.concat function concatenates strings in a table, producing a string result:
local t = { "con", "catenate" }
local a = table.concat(t) -- "concatenate"
local t = { "two", "words" }
local a = table.concat(t, " ") -- "two words"
The string.format function takes a format pattern with a list of compatible values, producing a string result:
local b = 2
local c = "words"
local a = string.format("%i %s", b, c) -- "2 words"
local t = { 2, "words" }
local a = string.format("%i %s", unpack(t)) -- "2 words"
If you are accumulating a lot of strings that you eventually want to concatenate, you can use a table as a temporary data structure and concatenate when you are done accumulating:
local t = {}
for i = 1, 1000 do
table.insert(t, tostring(i))
end
local a = table.concat(t) -- "1234...9991000"
For a very large number of strings, you can concatenate incrementally. See LTN 9: Creating Strings Piece by Piece and related discussions.
You should try the table.concat method.
Maybe this other question can help you:
Lua table.concat
Checkout this tutorial http://lua-users.org/wiki/TableLibraryTutorial
this code works:
function utf(regAddr, length)
stringTable = {}
table.insert(stringTable, {mb:readregisters(regAddr-1,length)})
for key, value in pairs(stringTable) do
t = {}
for i=1, length do
v = value[i]
v = lmcore.inttohex(v, 4)
v = cnv.hextostr(v)
table.insert(t, v)
end
a = table.concat(t)
end
end
-- function(regAddr, length)
utf(30,20)

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.

Resources