Change number after dollar sign to 0 in string - ruby

What I am trying to do is to change number that comes after $ sign into 0 in a string. I could do simple "find $ sign then change next thing after it into 0", but the problem is that number may have different number of digits. Another problem is that number might be non-integer like "2.5" so it has to tolerate comma, or negative numbers like "-2"
For example:
I have an equation which is string type: x^(-2) + 4x + 123 + 42.2 + 1
I write it as follows: x^($-2) + $4x + $123 + $42.2 + 1
Output that I am trying to get should be: x^(0) + 0x + 0 + 1
Do you have an idea how to do that?
For now I have came up with idea, but I don't know if such method exist in ruby.
x=0
while index('$',x+1) do
x = index('$',x+1)
#function that does translating
end
In the loop, there could be a function that trims every digit until it find non-numeric character (with exception of starting - and . imitating negative or floating point number) and then puts in that place "0".

r = /
\$ # match '$'
(?: # begin a non-capture group
-(?>\d) # match a hyphen followed by a digit in a positive lookahead
| # or
[\d,.]+ # match one of the characters one or more times
) # end the non-capture group
/x # free-spacing regex definition mode
which is conventionally written as follows.
r = /\$(?:-(?>\d)|[\d,.]+)/
"x^($-2) + $4,000x + $123 + $42.2 + 1".gsub(r, '0')
#=> "x^(0) + 0x + 0 + 0 + 1"
"x^($-2) + $4x + $-123- $42.2 + 1".gsub(r, '0')
#=> "x^(0) + 0x + 023- 0 + 1"

You could use regex with String#gsub like follows:
"x^($-2) + $4,000x + $123 + $42.2 + 1".gsub(/\$-?\d+(\,\d+)*(\.\d+)?/,'0')
#=> "x^(0) + 0x + 0 + 0 + 1"

Related

Caesar's cypher encryption algorithm

Caesar's cypher is the simplest encryption algorithm. It adds a fixed value to the ASCII (unicode) value of each character of a text. In other words, it shifts the characters. Decrypting a text is simply shifting it back by the same amount, that is, it substract the same value from the characters.
My task is to write a function that:
accepts two arguments: the first is the character vector to be encrypted, and the second is the shift amount.
returns one output, which is the encrypted text.
needs to work with all the visible ASCII characters from space to ~ (ASCII codes of 32 through 126). If the shifted code goes outside of this range, it should wrap around. For example, if we shift ~ by 1, the result should be space. If we shift space by -1, the result should be ~.
This is my MATLAB code:
function [coded] = caesar(input_text, shift)
x = double(input_text); %converts char symbols to double format
for ii = 1:length(x) %go through each element
if (x(ii) + shift > 126) & (mod(x(ii) + shift, 127) < 32)
x(ii) = mod(x(ii) + shift, 127) + 32; %if the symbol + shift > 126, I make it 32
elseif (x(ii) + shift > 126) & (mod(x(ii) + shift, 127) >= 32)
x(ii) = mod(x(ii) + shift, 127);
elseif (x(ii) + shift < 32) & (126 + (x(ii) + shift - 32 + 1) >= 32)
x(ii) = 126 + (x(ii) + shift - 32 + 1);
elseif (x(ii) + shift < 32) & (126 + (x(ii) + shift - 32 + 1) < 32)
x(ii) = abs(x(ii) - 32 + shift - 32);
else x(ii) = x(ii) + shift;
end
end
coded = char(x); % converts double format back to char
end
I can't seem to make the wrapping conversions correctly (e.g. from 31 to 126, 30 to 125, 127 to 32, and so on). How should I change my code to do that?
Before you even start coding something like this, you should have a firm grasp of how to approach the problem.
The main obstacle you encountered is how to apply the modulus operation to your data, seeing how mod "wraps" inputs to the range of [0 modPeriod-1], while your own data is in the range [32 126]. To make mod useful in this case we perform an intermediate step of shifting of the input to the range that mod "likes", i.e. from some [minVal maxVal] to [0 modPeriod-1].
So we need to find two things: the size of the required shift, and the size of the period of the mod. The first one is easy, since this is just -minVal, which is the negative of the ASCII value of the first character, which is space (written as ' ' in MATLAB). As for the period of the mod, this is just the size of your "alphabet", which happens to be "1 larger than the maximum value, after shifting", or in other words - maxVal-minVal+1. Essentially, what we're doing is the following
input -> shift to 0-based ("mod") domain -> apply mod() -> shift back -> output
Now take a look how this can be written using MATLAB's vectorized notation:
function [coded] = caesar(input_text, shift)
FIRST_PRINTABLE = ' ';
LAST_PRINTABLE = '~';
N_PRINTABLE_CHARS = LAST_PRINTABLE - FIRST_PRINTABLE + 1;
coded = char(mod(input_text - FIRST_PRINTABLE + shift, N_PRINTABLE_CHARS) + FIRST_PRINTABLE);
Here are some tests:
>> caesar('blabla', 1)
ans =
'cmbcmb'
>> caesar('cmbcmb', -1)
ans =
'blabla'
>> caesar('blabla', 1000)
ans =
'5?45?4'
>> caesar('5?45?4', -1000)
ans =
'blabla'
We can solve it using the idea of periodic functions :
periodic function repeats itself every cycle and every cycle is equal to 2π ...
like periodic functions ,we have a function that repeats itself every 95 values
the cycle = 126-32+1 ;
we add one because the '32' is also in the cycle ...
So if the value of the character exceeds '126' we subtract 95 ,
i.e. if the value =127(bigger than 126) then it is equivalent to
127-95=32 .
&if the value is less than 32 we subtract 95.
i.e. if the value= 31 (less than 32) then it is equivalent to 31+95
=126..
Now we will translate that into codes :
function out= caesar(string,shift)
value=string+shift;
for i=1:length(value)
while value(i)<32
value(i)=value(i)+95;
end
while value(i)>126
value(i)=value(i)-95;
end
end
out=char(value);
First i converted the output(shift+ text_input) to char.
function coded= caesar(text_input,shift)
coded=char(text_input+shift);
for i=1:length(coded)
while coded(i)<32
coded(i)=coded(i)+95;
end
while coded(i)>126
coded(i)=coded(i)-95;
end
end
Here Is one short code:
function coded = caesar(v,n)
C = 32:126;
v = double(v);
for i = 1:length(v)
x = find(C==v(i));
C = circshift(C,-n);
v(i) = C(x);
C = 32:126;
end
coded = char(v);
end

How to write a function f("123")=123+12+23+1+2+3 as a recurrence relationship

I'm wondering if someone can help me try to figure this out.
I want f(str) to take a string str of digits and return the sum of all substrings as numbers, and I want to write f as a function of itself so that I can try to solve this with memoization.
It's not jumping out at me as I stare at
Solve("1") = 1
Solve("2") = 2
Solve("12") = 12 + 1 + 2
Solve("29") = 29 + 2 + 9
Solve("129") = 129 + 12 + 29 + 1 + 2 + 9
Solve("293") = 293 + 29 + 93 + 2 + 9 + 3
Solve("1293") = 1293 + 129 + 293 + 12 + 29 + 93 + 1 + 2 + 9 + 3
Solve("2395") = 2395 + 239 + 395 + 23 + 39 + 95 + 2 + 3 + 9 + 5
Solve("12395") = 12395 + 1239 + 2395 + 123 + 239 + 395 + 12 + 23 + 39 + 95 + 1 + 2 + 3 + 9 + 5
You have to break f down into two functions.
Let N[i] be the ith digit of the input. Let T[i] be the sum of substrings of the first i-1 characters of the input. Let B[i] be the sum of suffixes of the first i characters of the input.
So if the input is "12395", then B[3] = 9+39+239+1239, and T[3] = 123+12+23+1+2+3.
The recurrence relations are:
T[0] = B[0] = 0
T[i+1] = T[i] + B[i]
B[i+1] = B[i]*10 + (i+1)*N[i]
The last line needs some explanation: the suffixes of the first i+2 characters are the suffixes of the first i+1 characters with the N[i] appended on the end, as well as the single-character string N[i]. The sum of these is (B[i]*10+N[i]*i) + N[i] which is the same as B[i]*10+N[i]*(i+1).
Also f(N) = T[len(N)] + B[len(N)].
This gives a short, linear-time, iterative solution, which you could consider to be a dynamic program:
def solve(n):
rt, rb = 0, 0
for i in xrange(len(n)):
rt, rb = rt+rb, rb*10+(i+1)*int(n[i])
return rt+rb
print solve("12395")
One way to look at this problem is to consider the contribution of each digit to the final sum.
For example, consider the digit Di at position i (from the end) in the number xn-1…xi+1Diyi-1…y0. (I used x, D, and y just to be able to talk about the digit positions.) If we look at all the substrings which contain D and sort them by the position of D from the end of the number, we'll see the following:
D
xD
xxD
…
xx…xD
Dy
xDy
xxDy
…
xx…xDy
Dyy
xDyy
xxDyy
…
xx…xDyy
and so on.
In other words, D appears in every position from 0 to i once for each prefix length from 0 to n-i-1 (inclusive), or a total of n-i times in each digit position. That means that its total contribution to the sum is D*(n-i) times the sum of the powers of 10 from 100 to 10i. (As it happens, that sum is exactly (10i+1−1)⁄9.)
That leads to a slightly simpler version of the iteration proposed by Paul Hankin:
def solve(n):
ones = 0
accum = 0
for m in range(len(n),0,-1):
ones = 10 * ones + 1
accum += m * ones * int(n[m-1])
return accum
By rearranging the sums in a different way, you can come up with this simple recursion, if you really really want a recursive solution:
# Find the sum of the digits in a number represented as a string
digitSum = lambda n: sum(map(int, n))
# Recursive solution by summing suffixes:
solve2 = lambda n: solve2(n[1:]) + (10 * int(n) - digitSum(n))/9 if n else 0
In case it's not obvious, 10*n-digitSum(n) is always divisible by 9, because:
10*n == n + 9*n == (mod 9) n mod 9 + 0
digitSum(n) mod 9 == n mod 9. (Because 10k == 1 mod n for any k.)
Therefore (10*n - digitSum(n)) mod 9 == (n - n) mod 9 == 0.
Looking at this pattern:
Solve("1") = f("1") = 1
Solve("12") = f("12") = 1 + 2 + 12 = f("1") + 2 + 12
Solve("123") = f("123") = 1 + 2 + 12 + 3 + 23 + 123 = f("12") + 3 + 23 + 123
Solve("1239") = f("1239") = 1 + 2 + 12 + 3 + 23 + 123 + 9 + 39 + 239 + 1239 = f("123") + 9 + 39 + 239 + 1239
Solve("12395") = f("12395") = 1 + 2 + 12 + 3 + 23 + 123 + 9 + 39 + 239 + 1239 + 5 + 95 + 395 + 2395 + 12395 = f("1239") + 5 + 95 + 395 + 2395 + 12395
To get the new terms, with n being the length of str, you are including the substrings made up of the 0-based index ranges of characters in str: (n-1,n-1), (n-2,n-1), (n-3,n-1), ... (n-n, n-1).
You can write a function to get the sum of the integers formed from the substring index ranges. Calling that function g(str), you can write the function recursively as f(str) = f(str.substring(0, str.length - 1)) + g(str) when str.length > 1, and the base case with str.length == 1 would just return the integer value of str. (The parameters of substring are the start index of a character in str and the length of the resulting substring.)
For the example Solve("12395"), the recursive equation f(str) = f(str.substring(0, str.length - 1)) + g(str) yields:
f("12395") =
f("1239") + g("12395") =
(f("123") + g("1239")) + g("12395") =
((f("12") + g("123")) + g("1239")) + g("12395") =
(((f("1") + g("12")) + g("123")) + g("1239")) + g("12395") =
1 + (2 + 12) + (3 + 23 + 123) + (9 + 39 + 239 + 1239) + (5 + 95 + 395 + 2395 + 12395)

How to print an equation in Ruby

I've got a question.
1.0X + 1.0Y + -7.0 = 0
How can I print an equation better?
For example, instead of +- 7.0 I'd like to print -7.0; or in a case with zero coefficients.
Thanks
Prints an equation with full control of formating
a = b = 1
c = -7
puts "%0.1fX + %0.1fY %s %0.1f = %d"%[ a, b, c < 0 ? '-' : '+', c.abs, 0 ]
output:
1.0X + 1.0Y - 7.0 = 0
Documentation: Ruby's % string operator / sprintf
With a few substitutions, you could achieve a much cleaner equation :
equation = "1.0X + 1.0Y - -0.0Z + -7.0 = 0"
new_equation = equation.gsub('+ -', '- ')
.gsub('- -', '+ ')
.gsub(/^\s*\+/, '') # Remove leading +
.gsub(/(?<=\d)\.0+(?=\D)/, '') # Remove trailing zeroes
.gsub(/\b1(?=[a-z])/i, '') # Remove 1 in 1X
.gsub(/[+-]? ?0[a-z] ?/i, '') # Remove 0Z
p new_equation
# "X + Y - 7 = 0"
By the way, as much as I love Ruby, I must say that Sympy is an awesome project. This library alone makes it worthwhile to learn the basic Python syntax.

How can I convert numbers to letters in VBS?

I want to take a number and convert it into lowercase a-z letters using VBScript.
For example:
1 converts to a
2 converts to b
27 converts to aa
28 converts to ab
and so on...
In particular I am having trouble converting numbers after 26 when converting to 2 letter cell names. (aa, ab, ac, etc.)
You should have a look at the Chr(n) function.
This would fit your needs from a to z:
wscript.echo Chr(number+96)
To represent multiple letters for numbers, (like excel would do it) you'll have to check your number for ranges and use the Mod operator for modulo.
EDIT:
There is a fast food Copy&Paste example on the web: How to convert Excel column numbers into alphabetical characters
Quoted example from microsoft:
For example: The column number is 30.
The column number is divided by 27: 30 / 27 = 1.1111, rounded down by the Int function to "1".
i = 1
Next Column number - (i * 26) = 30 -(1 * 26) = 30 - 26 = 4.
j = 4
Convert the values to alphabetical characters separately,
i = 1 = "A"
j = 4 = "D"
Combined together, they form the column designator "AD".
And its code:
Function ConvertToLetter(iCol As Integer) As String
Dim iAlpha As Integer
Dim iRemainder As Integer
iAlpha = Int(iCol / 27)
iRemainder = iCol - (iAlpha * 26)
If iAlpha > 0 Then
ConvertToLetter = Chr(iAlpha + 64)
End If
If iRemainder > 0 Then
ConvertToLetter = ConvertToLetter & Chr(iRemainder + 64)
End If
End Function
Neither of the solutions above work for the full Excel range from A to XFD. The first example only works up to ZZ. The second example has boundry problems explained in the code comments below.
//
Function ColumnNumberToLetter(ColumnNumber As Integer) As String
' convert a column number to the Excel letter representation
Dim Div As Double
Dim iMostSignificant As Integer
Dim iLeastSignificant As Integer
Dim Base As Integer
Base = 26
' Column letters are base 26 starting at A=1 and ending at Z=26
' For base 26 math to work we need to adjust the input value to
' base 26 starting at 0
Div = (ColumnNumber - 1) / Base
iMostSignificant = Int(Div)
' The addition of 1 is needed to restore the 0 to 25 result value to
' align with A to Z
iLeastSignificant = 1 + (Div - iMostSignificant) * Base
' convert number to letter
ColumnNumberToLetter = Chr(64 + iLeastSignificant)
' if the input number is larger than the base then the conversion we
' just did is the least significant letter
' Call the function again with the remaining most significant letters
If ColumnNumber > Base Then
ColumnNumberToLetter = ColumnNumberToLetter(iMostSignificant) & ColumnNumberToLetter
End If
End Function
//
try this
function converts(n)
Dim i, c, m
i = n
c = ""
While i > 26
m = (i mod 26)
c = Chr(m+96) & c
i = (i - m) / 26
Wend
c = Chr(i+96) & c
converts = c
end function
WScript.Echo converts(1000)

How do I describe all integers in Ruby

I'm trying to write a basic program that spits out the English version of a number when the user inputs a numeral:
input = 44
output = fourty four
Is there a way to describe all integers?
Basically I want the execution to look something like:
number = gets.chomp
if number != (whatever the nomenclature is for integer)
puts 'Please enter a positive number'
or something to that effect.
You can do that with the numbers_and_words gem:
https://github.com/kslazarev/numbers_and_words
It supports languages other than english as well.
For example:
21.to_words
=> "twenty-one"
44.to_words
=> "forty-four"
I modified the Fixnum class and added a method in_words. What I did is I broke each number up into groups of three, so 100000 turns into [100, 000] and 123456789 turns into [123, 456, 789] or 1543 turns into [1, 453] then I went element by element and named every number in the element and added the appropriate word, like hundred and thousand. If you have any questions I am happy to explain!
class Fixnum
LOW = %w(zero one two three four five six seven
eight nine ten eleven twelve thirteen fourteen
fifteen sixteen seventeen eighteen nineteen)
TWO_DIGIT = %w(ten twenty thirty forty fifty sixty seventy eighty ninety)
BIG_NUMS = %w(hundred thousand million billion trillion)
def in_words
# Break up number into bytes with three bits each
# Then turn each byte into words
# Break into bytes
number = self.to_s.reverse
bytes = []
num_bytes = (number.length.to_f / 3.0).ceil()
num_bytes.times { |x| bytes << number[(x*3)..(x*3)+2].reverse }
#puts bytes.reverse.join(",")
# Turn bytes into words bit by bit
word = []
text = ""
bytes.each_with_index do |byte, i|
text = ""
# First bit
text = LOW[byte[0].to_i] if (byte.length == 3 && byte[0].to_i != 0) || byte.length == 1
# Add hundred if 3 bits
text += " hundred" if byte.length == 3 && byte[0].to_i != 0
# Second bit
if byte.length == 3 # Three bits
if byte[1].to_i > 1 # Second bit greater than teens
text += " " + TWO_DIGIT[byte[1].to_i + (-1)]
elsif byte[1].to_i != 0 # Second bit not zero
text += " " + LOW[byte[1..2].to_i]
end
elsif byte.length == 2 # Two bits
if byte[0].to_i > 1 # Greater than teens
text += " " + TWO_DIGIT[byte[0].to_i + (-1)]
text += " " + LOW[byte[1].to_i] if byte[1].to_i != 0
else # Less than twenty
text += LOW[byte[0..1].to_i]
end
end
# Third bit if three bytes and second bit > teens and third bit nonzero
text += " " + LOW[byte[2].to_i] if byte[1].to_i != 1 && byte[2].to_i > 0 && byte.length > 2
# Add trillion/billion/million/thousand
text += " " + BIG_NUMS[i] if i != 0 && byte.to_i != 0
word << text.strip if text.strip != ""
end
word.reverse.join(" ")
end
end
Because I modified the Fixnum object, you can call this from any Fixnum e.g. 44.in_words
EDIT: It looks like you might be trying to check input for integers. I would recommend making a function to handle that:
def check_input(i)
if !(i =~ /^[0-9]+$/)
puts "Sorry, that is an invalid input! Please try again"
i = check_input(gets.chomp)
end
i.to_i
end
I think the best way to handle that is with regex (pattern matching). Basically your function checks if the input isn't a number, then it asks for input again. If it is a number, then the function returns the number. /^[0-9]+$/ is the regex. ^ means start of the line and $ means end of the line. [0-9] matches any digit zero through nine (as the Tin Man commented, you can also use \d to represent any digit and it is equivalent), and + means match the previous thing (any digit) at least once.

Resources