Small basic random letters - random

I'm batch file programmer but I'm experimenting with Small Basic. I know how to generate random numbers as a variable:
Math.getrandomnumber(number)
but I'm not sure how to generate random letters

Here you are! Like Tobberoth said, use text.GetCharacter for this. here is the code:
RandNum = Math.GetRandomNumber(25) + 65 'Get a number between 65 and 90 (See ASCII)
RandText = Text.GetCharacter(RandNum)
TextWindow.WriteLine(RandText)

I don't really know, but if you are dealing with just a few letters, for example ABC, I would do this:
Code:
number = Math.GetRandomNumber(3)
If number = 1 Then
letter = A
Elseif number = 2 Then
letter = B
Elseif number = 3 Then
letter = C
EndIf
This should help.

Just to round out the list of suggestions, you can do random anything using arrays.
hex[0] = "0"
hex[1] = "1"
hex[2] = "2"
...
hex[10] = "A"
hex[11] = "B"
hex[12] = "C"
hex[13] = "D"
hex[14] = "E"
hex[15] = "F"
randomHexDigit = hex[Math.GetRandomNumber(16) - 1]
The above will produce a random hex digit from the array.

Related

How to return matches and non matches when comparing two ranges/arrays

I'm attempting to return a count of the total number of matching and non-matching entries in a set of two ranges.
I'm trying to avoid looping over the array twice like this:
#expected output:
#inside: 421 | outside: 55
constant_range = 240..960
sample_range = 540..1015
sample_range_a = sample_range.to_a
def generate_range
inside = sample_range_a.select { |val| constant_range.include?(val) }.count
outside = sample_range_a.select { |val| !constant_range.include?(val) }.count
end
# I was thinking of a counter, but thought that would be even more ineffective
def generate_range
a = 0
b = 0
sample_range_a.select { |val| constant_range.include?(val) ? a++ : b++ }
end
I don't know if this is entirely your case, but if they're always number ranges with an interval of 1 and not any arbitrary array, the solution can be optimized to O(1), unlike the other methods using to_a that are at least O(n). In other words, if you have a BIG range, those array solutions would choke badly.
Assuming that you'll always use an ascending range of numbers with interval of 1, it means you can count them just by using size (count would be our enemy in this situation).
With that said, using simple math you can first check if the ranges may intersect, if not, just return 0. Otherwise, you can finally calculate the new range interval and get its size.
def range_intersection_count(x, y)
return 0 if x.last < y.first || y.last < x.first
([x.begin, y.begin].max..[x.max, y.max].min).size
end
This will count the number of elements that intersect in two ranges in O(1). You can test this code with something like
range_intersection_count(5000000..10000000000, 3000..1000000000000)
and then try the same input with the other methods and watch your program hang.
The final solution would look something like this:
constant_range = (240..960)
sample_range = (540..1015)
inside_count = range_intersection_count(constant_range, sample_range) # = 421
outside_count = sample_range.size - inside_count # = 55
constant_range = (240..960).to_a
sample_range = (540..1015).to_a
inside_count = (sample_range & constant_range).count #inside: 421
outside_count = sample_range.count - inside_count #outside: 55
You can use - (difference) in Ruby:
constant_range = (240..960).to_a
sample_range = (540..1015).to_a
puts (sample_range - constant_range).count # 55

Float - two digits after comma - how to?

I tried to execute a calculation in Ruby. The result I get is 1589.5833333333333. I would like to limitat the numbers of digits after the comma.
The result should always be limited to 2 digits as followed:
1589.58
Question #1 = how can I set the limitation?
Question #2 = how can I round up 1589.60 or down 1589.55
Many thanks for help. Language is ruby
Other option but keeping the object as Float:
n = 1589.5833333333333
m = n.truncate(2) #=> 1589.58
h = n.round(1) #=> 1589.6 # for the last zero you need to format the string
And a tricky:
k = (n*100).to_i.digits.tap{ |ary| ary.first > 5 ? ary[0] = 5 : ary[0] = 0 }.reverse.join('').to_i/100.0
#=> 1589.55
For question 1:
num = 1589.5833333333333
printf('%.2f', num)
=> 1589.58
For question 2 to round up to first digit:
num = 1589.5833333333333
printf('%.2f', num.round(1))
=> 1589.60
1589.55 is a bit of an arbitrary number, rounding down would usually be calculated as 1589.58. I don't know of any Ruby function that does that off-hand.

A simple Increasing Mathematical Algorithm

I actually tried to search this, I'm sure this basic algorithm is everywhere on internet, CS textbooks etc, but I cannot find the right words to search it.
What I want from this algorithm to do is write "A" and "B" with the limit always increasing by 2. Like I want it to write A 3 times, then B 5 times, then A 7 times, then B 9 times and so on. And I plan to have 100 elements in total.
Like: AAABBBBBAAAAAAABBBBBBBBB...
I only want to use a single "for loop" for the entire 100 elements starting from 1 to 100. And just direct/sort "A" and "B" through "if/else if/ else".
I'm just asking for the basic mathematical algorithm behind it, showing it through any programming language would be better or redirecting me to such topic would also be fine.
You can do something like this:
There might be shorter answers, but I find this one easy to understand.
Basically, you keep a bool variable that will tell you if it's A's turn or Bs. Then we keep a variable switch that will tell us when we should switch between them. times is being updated with the repeated times we need to print the next character.
A_B = true
times = 3 // 3,5,7,9,...
switch = 3 // 3,8,15,24,...
for (i from 1 to 100)
if (A_B)
print 'A'
else
print 'B'
if (i == switch)
times += 2
switch += times
A_B = !A_B
Python:
for n in range(1, 101):
print "BA"[(int(sqrt(n)) % 2)],
The parity of the square roots of the integers follows that pattern. (Think that (n+1)²-n² = 2n+1.)
If you prefer to avoid the square root, it suffices to use an extra variable that represents the integer square root and keep it updated
r= 1
for n in range(1, 101):
if r * r <= n:
r+= 1
print "AB"[r % 2],
Here is the snippet you can test on this page. It is an example for about 500 letters totally, sure you can modify it for 100 letters. It is quite flexible that you can change the constants to produce lot of different strings in the same manner.
var toRepeat = ['A', 'B'];
var result='', j, i=3;
var sum=i;
var counter = 0;
while (sum < 500) {
j = counter % 2;
result = result + toRepeat[j].repeat(i);
sum = sum + i;
i = i + 2;
counter++;
}
document.getElementById('hLetters').innerHTML=result;
console.log(result);
<div id="hLetters"></div>
If you want it to be exactly 500 / 100 letters, just use a substring function to trim off the extra letters from the end.
To get 100 groups of A and B with increasing length of 3, 5, 7 and so on, you can run this Python code:
''.join(('B' if i % 2 else 'A') * (2 * i + 3) for i in range(100))
The output is a string of 10200 characters.
If you want the output to have only 100 characters, you can use:
import math
''.join(('B' if math.ceil(math.sqrt(i)) % 2 else 'A') for i in range(2, 102))
In js you can start with somethink like this :
$res ="";
count2 = 0;
for (i=2;i<100; i = i+2) {
count = 0;
alert(i);
while (count < i ) {
$res = $res.concat(String.fromCharCode(65+count2));
count++;
}
count2++;
}
alert ($res);

Convert alphanumeric string to given values for each, then add them for a total number

I'm having a difficult time wording exactly what I'm doing, but basically I have variable length alphanumeric data being fed to a program, and I want to find out the total "pixel width" of the string, based on a fixed list of A = 3 pxl, B = 3 pxl, I = 1 pxl, etc...
I would list all of the pixel values of each letter and number, and then would like the script to take the input: ex. "THIS IS THE STRING", and convert it to the numbers I've assigned add them up and total them giving me the total sum as an output (I would also assign a number for a space " " and punctuation).
So: "THIS IS A STRING" would be "3+3+1+3+2+1+3+2+3+3+3+2+3+3+3+1+3+3 = 45"
You need a table/array of pixel widthes indexed by ASCII codes. Then you can loop over the string's characters and sum the widthes. Like:
>> Dim a(255)
>> a(65) = 3
>> a(66) = 3
>> a(Asc("I")) = 1
>> s = "AIB"
>> n = 0
>> For p = 1 To Len(s)
>> n = n + a(Asc(Mid(s, p, 1)))
>> Next
>> WScript.Echo n
>>
7

Algorithm Issue: letter combinations

I'm trying to write a piece of code that will do the following:
Take the numbers 0 to 9 and assign one or more letters to this number. For example:
0 = N,
1 = L,
2 = T,
3 = D,
4 = R,
5 = V or F,
6 = B or P,
7 = Z,
8 = H or CH or J,
9 = G
When I have a code like 0123, it's an easy job to encode it. It will obviously make up the code NLTD. When a number like 5,6 or 8 is introduced, things get different. A number like 051 would result in more than one possibility:
NVL and NFL
It should be obvious that this gets even "worse" with longer numbers that include several digits like 5,6 or 8.
Being pretty bad at mathematics, I have not yet been able to come up with a decent solution that will allow me to feed the program a bunch of numbers and have it spit out all the possible letter combinations. So I'd love some help with it, 'cause I can't seem to figure it out. Dug up some information about permutations and combinations, but no luck.
Thanks for any suggestions/clues. The language I need to write the code in is PHP, but any general hints would be highly appreciated.
Update:
Some more background: (and thanks a lot for the quick responses!)
The idea behind my question is to build a script that will help people to easily convert numbers they want to remember to words that are far more easily remembered. This is sometimes referred to as "pseudo-numerology".
I want the script to give me all the possible combinations that are then held against a database of stripped words. These stripped words just come from a dictionary and have all the letters I mentioned in my question stripped out of them. That way, the number to be encoded can usually easily be related to a one or more database records. And when that happens, you end up with a list of words that you can use to remember the number you wanted to remember.
It can be done easily recursively.
The idea is that to handle the whole code of size n, you must handle first the n - 1 digits.
Once you have all answers for n-1 digits, the answers for the whole are deduced by appending to them the correct(s) char(s) for the last one.
There's actually a much better solution than enumerating all the possible translations of a number and looking them up: Simply do the reverse computation on every word in your dictionary, and store the string of digits in another field. So if your mapping is:
0 = N,
1 = L,
2 = T,
3 = D,
4 = R,
5 = V or F,
6 = B or P,
7 = Z,
8 = H or CH or J,
9 = G
your reverse mapping is:
N = 0,
L = 1,
T = 2,
D = 3,
R = 4,
V = 5,
F = 5,
B = 6,
P = 6,
Z = 7,
H = 8,
J = 8,
G = 9
Note there's no mapping for 'ch', because the 'c' will be dropped, and the 'h' will be converted to 8 anyway.
Then, all you have to do is iterate through each letter in the dictionary word, output the appropriate digit if there's a match, and do nothing if there isn't.
Store all the generated digit strings as another field in the database. When you want to look something up, just perform a simple query for the number entered, instead of having to do tens (or hundreds, or thousands) of lookups of potential words.
The general structure you want to hold your number -> letter assignments is an array or arrays, similar to:
// 0 = N, 1 = L, 2 = T, 3 = D, 4 = R, 5 = V or F, 6 = B or P, 7 = Z,
// 8 = H or CH or J, 9 = G
$numberMap = new Array (
0 => new Array("N"),
1 => new Array("L"),
2 => new Array("T"),
3 => new Array("D"),
4 => new Array("R"),
5 => new Array("V", "F"),
6 => new Array("B", "P"),
7 => new Array("Z"),
8 => new Array("H", "CH", "J"),
9 => new Array("G"),
);
Then, a bit of recursive logic gives us a function similar to:
function GetEncoding($number) {
$ret = new Array();
for ($i = 0; $i < strlen($number); $i++) {
// We're just translating here, nothing special.
// $var + 0 is a cheap way of forcing a variable to be numeric
$ret[] = $numberMap[$number[$i]+0];
}
}
function PrintEncoding($enc, $string = "") {
// If we're at the end of the line, then print!
if (count($enc) === 0) {
print $string."\n";
return;
}
// Otherwise, soldier on through the possible values.
// Grab the next 'letter' and cycle through the possibilities for it.
foreach ($enc[0] as $letter) {
// And call this function again with it!
PrintEncoding(array_slice($enc, 1), $string.$letter);
}
}
Three cheers for recursion! This would be used via:
PrintEncoding(GetEncoding("052384"));
And if you really want it as an array, play with output buffering and explode using "\n" as your split string.
This kind of problem are usually resolved with recursion. In ruby, one (quick and dirty) solution would be
#values = Hash.new([])
#values["0"] = ["N"]
#values["1"] = ["L"]
#values["2"] = ["T"]
#values["3"] = ["D"]
#values["4"] = ["R"]
#values["5"] = ["V","F"]
#values["6"] = ["B","P"]
#values["7"] = ["Z"]
#values["8"] = ["H","CH","J"]
#values["9"] = ["G"]
def find_valid_combinations(buffer,number)
first_char = number.shift
#values[first_char].each do |key|
if(number.length == 0) then
puts buffer + key
else
find_valid_combinations(buffer + key,number.dup)
end
end
end
find_valid_combinations("",ARGV[0].split(""))
And if you run this from the command line you will get:
$ ruby r.rb 051
NVL
NFL
This is related to brute-force search and backtracking
Here is a recursive solution in Python.
#!/usr/bin/env/python
import sys
ENCODING = {'0':['N'],
'1':['L'],
'2':['T'],
'3':['D'],
'4':['R'],
'5':['V', 'F'],
'6':['B', 'P'],
'7':['Z'],
'8':['H', 'CH', 'J'],
'9':['G']
}
def decode(str):
if len(str) == 0:
return ''
elif len(str) == 1:
return ENCODING[str]
else:
result = []
for prefix in ENCODING[str[0]]:
result.extend([prefix + suffix for suffix in decode(str[1:])])
return result
if __name__ == '__main__':
print decode(sys.argv[1])
Example output:
$ ./demo 1
['L']
$ ./demo 051
['NVL', 'NFL']
$ ./demo 0518
['NVLH', 'NVLCH', 'NVLJ', 'NFLH', 'NFLCH', 'NFLJ']
Could you do the following:
Create a results array.
Create an item in the array with value ""
Loop through the numbers, say 051 analyzing each one individually.
Each time a 1 to 1 match between a number is found add the correct value to all items in the results array.
So "" becomes N.
Each time a 1 to many match is found, add new rows to the results array with one option, and update the existing results with the other option.
So N becomes NV and a new item is created NF
Then the last number is a 1 to 1 match so the items in the results array become
NVL and NFL
To produce the results loop through the results array, printing them, or whatever.
Let pn be a list of all possible letter combinations of a given number string s up to the nth digit.
Then, the following algorithm will generate pn+1:
digit = s[n+1];
foreach(letter l that digit maps to)
{
foreach(entry e in p(n))
{
newEntry = append l to e;
add newEntry to p(n+1);
}
}
The first iteration is somewhat of a special case, since p-1 is undefined. You can simply initialize p0 as the list of all possible characters for the first character.
So, your 051 example:
Iteration 0:
p(0) = {N}
Iteration 1:
digit = 5
foreach({V, F})
{
foreach(p(0) = {N})
{
newEntry = N + V or N + F
p(1) = {NV, NF}
}
}
Iteration 2:
digit = 1
foreach({L})
{
foreach(p(1) = {NV, NF})
{
newEntry = NV + L or NF + L
p(2) = {NVL, NFL}
}
}
The form you want is probably something like:
function combinations( $str ){
$l = len( $str );
$results = array( );
if ($l == 0) { return $results; }
if ($l == 1)
{
foreach( $codes[ $str[0] ] as $code )
{
$results[] = $code;
}
return $results;
}
$cur = $str[0];
$combs = combinations( substr( $str, 1, $l ) );
foreach ($codes[ $cur ] as $code)
{
foreach ($combs as $comb)
{
$results[] = $code.$comb;
}
}
return $results;}
This is ugly, pidgin-php so please verify it first. The basic idea is to generate every combination of the string from [1..n] and then prepend to the front of all those combinations each possible code for str[0]. Bear in mind that in the worst case this will have performance exponential in the length of your string, because that much ambiguity is actually present in your coding scheme.
The trick is not only to generate all possible letter combinations that match a given number, but to select the letter sequence that is most easy to remember. A suggestion would be to run the soundex algorithm on each of the sequence and try to match against an English language dictionary such as Wordnet to find the most 'real-word-sounding' sequences.

Resources