How do I fix the error "subscript out of range" in QBASIC? - subscript

I'm trying to create a code that generates random numbers within the range 10-30 but making sure that no number is repeated. It shows "subscript out of range" on NumArray(Count) = Count when I run the code.
'Make an array of completely sorted numbers
FOR Count = 10 TO 30
NumArray(Count) = Count
NEXT Count
RANDOMIZE TIMER
FOR Count = 10 TO 30
Number = (RND * (31 - Count)) + 10
PRINT #1, NumArray(Number)
FOR Counter = Number TO 30 - Count
NumArray(Counter) = NumArray(Counter + 1)
NEXT Counter
NEXT Count
This isn't actually my code. Copied and pasted for my assignment.

It looks like you're missing some DIM statements.
Variables containing numbers have type SINGLE by default, so you might see something like FOR Counter = 18.726493 TO 20 because the RND function returns a number between 0 and 1, excluding 1, meaning you will be trying to use NumArray(18.726493) which will not work.
Arrays that are not explicitly declared can only have 11 items with an index from 0 to 10, but the range 10-30 requires you to store 21 items (30 - 10 + 1 = 21). You can also specify a custom upper and lower bound if it will make your code easier for you to understand. Add these lines before the first line in your code shown above:
DIM Number AS INTEGER
DIM NumArray(10 TO 30) AS INTEGER
This will ensure Number only contains integers (any fractional values are rounded to the nearest integer), and NumArray will work from NumArray(10) to NumArray(30), but you can't use NumArray(9), NumArray(8), NumArray(31), etc. The index must be in the range 10-30.
I think that should fix your code, but I don't know for certain since I don't fully understand how it is supposed to work. At the very least, it will fix the type and subscript problems in your code.

You need to declare the array:
'Make an array of completely sorted numbers
DIM NumArray(30) AS INTEGER
FOR Count = 10 TO 30
NumArray(Count) = Count
NEXT Count
RANDOMIZE TIMER
FOR Count = 10 TO 30
Number = (RND * (31 - Count)) + 10
PRINT #1, NumArray(Number)
FOR Counter = Number TO 30 - Count
NumArray(Counter) = NumArray(Counter + 1)
NEXT Counter
NEXT Count

Related

What's the proper way to find the last parcel of an array?

I'm doing some codewars and arr[index] keeps returning nil. I've done this a few different ways, and I'm sure the array exists, as well as the index. What's wrong here, is it syntax?
As I've mentioned in the title, I want to find the last digit of the array.
if arr[index] <= 0 then
return -1
end
Full Code:
local solution = {}
function solution.newAvg(arr, navg)
local currentAverage = 0
local index = 0
for i, v in pairs(arr) do
index = i
currentAverage = currentAverage + v
end
if arr[index] <= 0 then
return -1
end
return math.ceil(((index+1) * navg) - currentAverage)
end
return solution
I see two issues with your code:
Edge case: Empty array
If arr = {}, the loop for i, v in pairs(arr) do won't execute at all and index will remain at 0. Since arr is empty, arr[0] will be nil and arr[index] <= 0 will fail with an "attempt to compare a nil value" error.
Lack of ordering guarantee
You use pairs rather than ipairs to loop over what I assume is a list. This means keys & values might be traversed in any order. In practice pairs usually (but not always!) traverses the list part of a table in the same order as ipairs, but the reference manual clearly states that you can't rely on no specific order. I don't think CodeWars is this advanced but consider the possibility that pairs may be overridden to deliberately shuffle the order of traversal in order to check whether you're relying on the dreaded "undefined behavior". If this is the case, your "last index" might actually be any index that happens to be visited last, obviously breaking your algorithm.
Fixes
I'll assume arr is an "array", that is, it only contains keys from 1 to n and all values are non-nil (i.e. there are no holes). Then you can (and should!) use ipairs to loop over the "array":
for i, v in ipairs(arr) do ... end
I don't know the problem statement so it's hard to tell how an empty array should be handled. I'll assume that it should probably return 0. You could add a simply early return at the top of the function for that: if arr[1] == nil then return 0 end. Nonempty arrays will always have arr[1] ~= nil.
I want to find the last digit of the array.
If you mean the last integer (or entry/item) of the array:
local last = array[#array]
If you mean the last digit (for example array = {10, 75, 44, 62} and you want 2), then you can get the last item and then get the last digit using modulo 10:
local last = array[#array] % 10
for i, v in pairs(arr) do
index = i
currentAverage = currentAverage + v
end
Just a reminder:
#array returns the number of items in a table.
In Lua, arrays are implemented using integer-indexed tables.
There's a difference between pairs() and ipairs().
Regarding point 3 above, the following code:
local array = {
[1] = 12,
[2] = 32,
[3] = 41,
[4] = 30,
[5] = 14,
[6] = 50,
[7] = 62,
[8] = 57
}
for key, value in pairs(array) do
print(key, value)
end
produces the following output (note that the order of keys is not respected):
8 57
1 12
2 32
3 41
4 30
5 14
6 50
7 62
while the same code above with pairs() replaced with ipairs() gives:
1 12
2 32
3 41
4 30
5 14
6 50
7 62
8 57
So, this might be the cause of your problem.

Excel 2010 Macro does not find value

I have a macro that searches but does not find the “7” (If Right(pair, 2) = 7 Then). The thing is when I change the number to 11 or 12 etc. (any two digits) and the findXX in the code, it works fine. Does anyone know what’s occurring and what is the exact change I need to do.
Option Explicit
Sub DivideSomeStuff()
Dim pair As Range, accumulator As Range
Dim findSeven As Double
Dim remainder As Long
For Each pair In Range("B30, F30, J30")
If Right(pair, 2) = 7 Then
If pair.Offset(0, 2) <= 12 Then
remainder = 0
Else
remainder = pair.Offset(0, 2) Mod 10
End If
findSeven = (pair.Offset(0, 2) - remainder) / 10
For Each accumulator In Range("A36, D36, G36, J36, M36, A40, D40, G40, J40, M40")
If accumulator.Offset(-1, 0) = Val(Left(pair, InStr(pair, "-") - 1)) Then
accumulator.Value = accumulator.Value + remainder
End If
accumulator.Value = accumulator.Value + findSeven
Next accumulator
End If
Next pair
End Sub
Change it from ...
Right(pair, 2) = 7
... to ...
Right(pair, 1) = 7
You’re currently getting the 2 right values when 7 is a single character.
You may need to put quotes around the 7 too, see if works without them though.

generating series of number 0,3,5,8,10,13,15,18

i want to generate a series of number through looping.
my series will contain numbers like 0,3,5,8,10,13,15,18 and so on.
i try to take reminder and try to add 2 and 3 but it wont work out.
can any one please help me in generating this series.
You can just use an increment which toggles between 3 and 2, e.g.
for (i = 0, inc = 3; i < 1000; i += inc, inc = 5 - inc)
{
printf("%d\n", i);
}
It looks like the the sequence starts at zero, and uses increments of 3 and 2. There are several ways of implementing this, but perhaps the simplest one would be iterating in increments of 5 (i.e. 3+2) and printing two numbers - position and position plus three.
Here is some pseudocode:
i = 0
REPEAT N times :
PRINT i
PRINT i + 3
i += 5
The iteration i=0 will print 0 and 3
The iteration i=5 will print 5 and 8
The iteration i=10 will print 10 and 13
The iteration i=15 will print 15 and 18
... and so on
I was pulled in with the tag generate-series, which is a powerful PostgreSQL function. This may have been tagged by mistake (?) but it just so happens that there would be an elegant solution:
SELECT ceil(generate_series(0, 1000, 25) / 10.0)::int;
generate_series() returns 0, 25, 50, 75 , ... (can only produces integer numbers)
division by 10.0 produces numeric data: 0, 2.5, 5, 7.5, ...
ceil() rounds up to your desired result.
The final cast to integer (::int) is optional.
SQL Fiddle.

Rounding to specific value?

I need to round a number, let's say 543 to either the hundreds or the tens place. It could be either one, as it's part of a game and this stage can ask you to do one or the other.
So for example, it could ask, "Round number to nearest tens", and if the number was 543, they would have to enter in 540.
However, I don't see a function that you can specify target place value to round at. I know there's an easy solution, I just can't think of one right now.
From what I see, the round function rounds the last decimal place?
Thanks
To rounding to 100's place
NSInteger num=543;
NSInteger deci=num%100;//43
if(deci>49){
num=num-deci+100;//543-43+100 =600
}
else{
num=num-deci;//543-43=500
}
To round to 10's place
NSInteger num=543;
NSInteger deci=num%10;//3
if(deci>4){
num=num-deci+100;//543-3+10 =550
}
else{
num=num-deci;//543-3=540
}
EDIT:
Tried to merge the above in one:
NSInteger num=543;
NSInteger place=100; //rounding factor, 10 or 100 or even more.
NSInteger condition=place/2;
NSInteger deci=num%place;//43
if(deci>=condition){
num=num-deci+place;//543-43+100 =600.
}
else{
num=num-deci;//543-43=500
}
You may just use an algorithm in your code:
For example, lets say that you need to round up a number to hundred's place.
int c = 543
int k = c % 100
if k > 50
c = (c - k) + 100
else
c = c - k
To round numbers, you can use the modulus operator, %.
The modulus operator gives you the remainder after division.
So 543 % 10 = 3, and 543 % 100 = 43.
Example:
int place = 10;
int numToRound=543;
// Remainder is 3
int remainder = numToRound%place;
if(remainder>(place/2)) {
// Called if remainder is greater than 5. In this case, it is 3, so this line won't be called.
// Subtract the remainder, and round up by 10.
numToRound=(numToRound-remainder)+place;
}
else {
// Called if remainder is less than 5. In this case, 3 < 5, so it will be called.
// Subtract the remainder, leaving 540
numToRound=(numToRound-remainder);
}
// numToRound will output as 540
NSLog(#"%i", numToRound);
Edit: My original answer was submitted before it was ready, because I accidentally hit a key to submit it. Oops.

How to generate random lines of text of a given length from a dictionary of words (bin-packing problem)?

I need to generate three lines of text (essentially jibberish) that are each 60 characters long, including a hard return at the end of each line. The lines are generated from a dictionary of words of various lengths (typically 1-8 characters). No word may be used more than once, and words must be separated by spaces. I think this is essentially a bin-packing problem.
The approach I've taken so far is to create a hashMap of the words, grouped by their lengths. I then choose a random length, pull a word of that length from the map, and append it to the end of the line I'm currently generating, accounting for spaces or a hard return. It works about half the time, but the other half of the time I'm getting stuck in an infinite loop and my program crashes.
One problem I'm running into is this: as I add random words to the lines, groups of words of a given length may become depleted. This is because there are not necessarily the same number of words of each length in the dictionary, e.g., there may only be one word with a length of 1. So, I might need a word of a given length, but there are no longer any words of that length available.
Below is a summary of what I have so far. I'm working in ActionScript, but would appreciate insight into this problem in any language. Many thanks in advance.
dictionary // map of words with word lengths as keys and arrays of corresponding words as values
lengths // array of word lengths, sorted numerically
min = lengths[0] // minimum word length
max = lengths[lengths.length - 1] // maximum word length
line = ""
while ( line.length < 60 ) {
len = lengths[round( rand() * ( lengths.length - 1 ) )]
if ( dictionary[len] != null && dictionary[len].length > 0 ) {
diff = 60 - line.length // number of characters needed to complete the line
if ( line.length + len + 1 == 60 ) {
// this word will complete the line exactly
line += dictionary[len].splice(0, 1) + "\n"
}
else if ( min + max + 2 >= diff ) {
// find the two word lengths that will complete the line
// ==> this is where I'm having trouble
}
else if ( line.length + len + 1 < 60 - max ) {
// this word will fit safely, so just add it
line += dictionary[len].splice(0, 1) + " "
}
if ( dictionary[len].length == 0 ) {
// delete any empty arrays and update min and max lengths accordingly
dictionary[len] = null
delete dictionary[len]
i = lengths.indexOf( len )
if ( i >= 0 ) {
// words of this length have been depleted, so
// update lengths array to ensure that next random
// length is valid
lengths.splice( i, 1 )
}
if ( lengths.indexOf( min ) == -1 ) {
// update the min
min = lengths[0]
}
if ( lengths.indexOf( max ) == -1 ) {
// update the max
max = lengths[lengths.length - 1]
}
}
}
}
You should think of an n-letter word as being n+1 letters, because each word has either a space or return after it.
Since all your words are at least 2 characters long, you don't ever want to get to a point where you have 59 characters filled in. If you get to 57, you need to pick something that is 2 letters plus the return. If you get to 58, you need a 1-letter word plus the return.
Are you trying to optimize for time? Can you have the same word multiple times? Multiple times in one line? Does it matter if your words are not uniformly distributed, e.g. a lot of lines contain "a" or "I" because those are the only one-letter words in English?
Here's the basic idea. For each line, start choosing word lengths, and keep track of the word lengths and total character count so far. As you get toward the end of the line, choose word lengths less than the number of characters you have left. (e.g. if you have 5 characters left, choose words in the range of 2-5 characters, counting the space.) If you get to 57 characters, pick a 3-letter word (counting return). If you get to 58 characters, pick a 2-letter word (counting return.)
If you want, you can shuffle the word lengths at this point, so all your lines don't end with short words. Then for each word length, pick a word of that length and plug it in.
dictionnary = Group your words by lengths (like you already do)
total_length = 0
phrase = ""
while (total_length < 60){
random_length = generate_random_number(1,8)
if (total_length + random_length > 60)
{
random_length = 60 - total_length // possibly - 1 if you cound \n and -2 if you
// append a blank anyway at the end
}
phrase += dictionnary.get_random_word_of_length(random_length) + " "
total_length += random_length + 1
}

Resources