Splitting numbers into smaller groups - python-3.x

I believe this question is leaning more towards developing the logic than implementation.
I have a 6 digit int value which I need to split into three, three digit numbers.
This is a trivial task but I cannot use any indexing or slicing operations.
Input -
rgb1 = 220020060
rgb2 = 189252201
My expected output is of the form
r1 , g1, b1 = 220, 020, 060
r2, g2, b2 = 189, 252, 201
I have tried using divmod() but unsure of how to get the middle set of values if it is of the form 0x0 where x is any single digit integer.
For example:
r, rest = divmod(rgb1,10**6)
r = 220, rest = 20060
But I am unsure as to how to proceed with extracting further numbers.

What I would do is convert the number to string if 0xx cases exists, as 'int' cannot display leading zeros.
My code:
def splitter(num):
r1, rest=divmod(num,10**6)
if len(str(r1)) !=3:
r1=str(r1)
r1=r1.zfill(3)
if len(str(rest)) !=6:
rest=str(rest)
rest=rest.zfill(6)
g1,rest=divmod(int(rest),10**3)
if len(str(g1)) !=3:
g1=str(g1)
g1=g1.zfill(3)
if len(str(rest)) !=3:
rest=str(rest)
rest=rest.zfill(3)
b1=rest
return r1,g1,b1
Output:
>>> splitter(220020060)
(220, '020', '060')
You can edit the code to display the output in the format you need!

Related

Padding with zeros in the middle of a string?

Padding a number with leading zeros has been answered here. But in my case I have a string character followed by digits. I want to add leading zeros after the string character, but before the digits, keeping the total length to 4. For example:
A1 -> A001
A12 -> A012
A123 -> A123
I have the following code that gets me what I want, but is there a shorter way to do this without using re to split my string into text and numbers first?
import re
mystr = 'A4'
elements = re.match(r"([a-z]+)([0-9]+)", mystr, re.I)
first, second = elements.groups()
print(first + '{:0>3}'.format(second))
output = A004
You could use the following to avoid using re:
def pad_center(s):
zeros = '0' * (4 - len(s))
first, *the_rest = list(s)
return first + zeros + ''.join(the_rest)
print(pad_center('A1'))
print(pad_center('A12'))
print(pad_center('A123'))
Or, if you want to use format() you could try this:
def pad_center(s):
zeros = '0' * (4 - len(s))
first, *the_rest = list(s)
return '{}{}{}'.format(first, zeros, ''.join(the_rest))
However, I am not aware of any way to add padding to the center of a string with the format string syntax without prior processing.

How to compute word scores in Scrabble using MATLAB

I have a homework program I have run into a problem with. We basically have to take a word (such as MATLAB) and have the function give us the correct score value for it using the rules of Scrabble. There are other things involved such as double word and double point values, but what I'm struggling with is converting to ASCII. I need to get my string into ASCII form and then sum up those values. We only know the bare basics of strings and our teacher is pretty useless. I've tried converting the string into numbers, but that's not exactly working out. Any suggestions?
function[score] = scrabble(word, letterPoints)
doubleword = '#';
doubleletter = '!';
doublew = [findstr(word, doubleword)]
trouble = [findstr(word, doubleletter)]
word = char(word)
gameplay = word;
ASCII = double(gameplay)
score = lower(sum(ASCII));
Building on Francis's post, what I would recommend you do is create a lookup array. You can certainly convert each character into its ASCII equivalent, but then what I would do is have an array where the input is the ASCII code of the character you want (with a bit of modification), and the output will be the point value of the character. Once you find this, you can sum over the points to get your final point score.
I'm going to leave out double points, double letters, blank tiles and that whole gamut of fun stuff in Scrabble for now in order to get what you want working. By consulting Wikipedia, this is the point distribution for each letter encountered in Scrabble.
1 point: A, E, I, O, N, R, T, L, S, U
2 points: D, G
3 points: B, C, M, P
4 points: F, H, V, W, Y
5 points: K
8 points: J, X
10 points: Q, Z
What we're going to do is convert your word into lower case to ensure consistency. Now, if you take a look at the letter a, this corresponds to ASCII code 97. You can verify that by using the double function we talked about earlier:
>> double('a')
97
As there are 26 letters in the alphabet, this means that going from a to z should go from 97 to 122. Because MATLAB starts indexing arrays at 1, what we can do is subtract each of our characters by 96 so that we'll be able to figure out the numerical position of these characters from 1 to 26.
Let's start by building our lookup table. First, I'm going to define a whole bunch of strings. Each string denotes the letters that are associated with each point in Scrabble:
string1point = 'aeionrtlsu';
string2point = 'dg';
string3point = 'bcmp';
string4point = 'fhvwy';
string5point = 'k';
string8point = 'jx';
string10point = 'qz';
Now, we can use each of the strings, convert to double, subtract by 96 then assign each of the corresponding locations to the points for each letter. Let's create our lookup table like so:
lookup = zeros(1,26);
lookup(double(string1point) - 96) = 1;
lookup(double(string2point) - 96) = 2;
lookup(double(string3point) - 96) = 3;
lookup(double(string4point) - 96) = 4;
lookup(double(string5point) - 96) = 5;
lookup(double(string8point) - 96) = 8;
lookup(double(string10point) - 96) = 10;
I first create an array of length 26 through the zeros function. I then figure out where each letter goes and assign to each letter their point values.
Now, the last thing you need to do is take a string, take the lower case to be sure, then convert each character into its ASCII equivalent, subtract by 96, then sum up the values. If we are given... say... MATLAB:
stringToConvert = 'MATLAB';
stringToConvert = lower(stringToConvert);
ASCII = double(stringToConvert) - 96;
value = sum(lookup(ASCII));
Lo and behold... we get:
value =
10
The last line of the above code is crucial. Basically, ASCII will contain a bunch of indexing locations where each number corresponds to the numerical position of where the letter occurs in the alphabet. We use these positions to look up what point / score each letter gives us, and we sum over all of these values.
Part #2
The next part where double point values and double words come to play can be found in my other StackOverflow post here:
Calculate Scrabble word scores for double letters and double words MATLAB
Convert from string to ASCII:
>> myString = 'hello, world';
>> ASCII = double(myString)
ASCII =
104 101 108 108 111 44 32 119 111 114 108 100
Sum up the values:
>> total = sum(ASCII)
total =
1160
The MATLAB help for char() says (emphasis added):
S = char(X) converts array X of nonnegative integer codes into a character array. Valid codes range from 0 to 65535, where codes 0 through 127 correspond to 7-bit ASCII characters. The characters that MATLABĀ® can process (other than 7-bit ASCII characters) depend upon your current locale setting. To convert characters into a numeric array, use the double function.
ASCII chart here.

MATLAB: Concatenate number value as string

I want to create a binary number in matlab and am having difficulty concatenating the numbers.
Here's what I tried so far:
testarray = zeros(10,10)
testarray = num2str(testarray) % Convert all values to type string
testarray(1,1) = num2str(1); % Fill with abitrary value
testarray(1,1) = strcat(testarray(1,1), num2str(0)); % Trying to make '10' here but instead I get this error: "Assignment has more non-singleton rhs dimensions than non-singleton subscripts"
Any help would be appreciated.
In your example, the problem is that '10' has size [1,2], but testarray(1,1) has size [1,1]. So you might consider using cells instead:
testarray = cell(5,5);
testarray{1,1} = strcat(testarray(1,1), num2str(0));
By the way, you should have a look at the function dec2bin.
From the documentation:
dec2bin(23)
ans =
10111
The resulting value is a string.
So if you want to concatenate two binary values (encoded as strings), just do:
['10' '11']
ans =
1011

How compiler is converting integer to string and vice versa

Many languages have functions for converting string to integer and vice versa. So what happens there? What algorithm is being executed during conversion?
I don't ask in specific language because I think it should be similar in all of them.
To convert a string to an integer, take each character in turn and if it's in the range '0' through '9', convert it to its decimal equivalent. Usually that's simply subtracting the character value of '0'. Now multiply any previous results by 10 and add the new value. Repeat until there are no digits left. If there was a leading '-' minus sign, invert the result.
To convert an integer to a string, start by inverting the number if it is negative. Divide the integer by 10 and save the remainder. Convert the remainder to a character by adding the character value of '0'. Push this to the beginning of the string; now repeat with the value that you obtained from the division. Repeat until the divided value is zero. Put out a leading '-' minus sign if the number started out negative.
Here are concrete implementations in Python, which in my opinion is the language closest to pseudo-code.
def string_to_int(s):
i = 0
sign = 1
if s[0] == '-':
sign = -1
s = s[1:]
for c in s:
if not ('0' <= c <= '9'):
raise ValueError
i = 10 * i + ord(c) - ord('0')
return sign * i
def int_to_string(i):
s = ''
sign = ''
if i < 0:
sign = '-'
i = -i
while True:
remainder = i % 10
i = i / 10
s = chr(ord('0') + remainder) + s
if i == 0:
break
return sign + s
I wouldn't call it an algorithm per se, but depending on the language it will involve the conversion of characters into their integral equivalent. Many languages will either stop on the first character that cannot be represented as an integer (e.g. the letter a), will blindly convert all characters into their ASCII value (e.g. the letter a becomes 97), or will ignore characters that cannot be represented as integers and only convert the ones that can - or return 0 / empty. You have to get more specific on the framework/language to provide more information.
String to integer:
Many (most) languages represent strings, on some level or another, as an array (or list) of characters, which are also short integers. Map the ones corresponding to number characters to their number value. For example, '0' in ascii is represented by 48. So you map 48 to 0, 49 to 1, and so on to 9.
Starting from the left, you multiply your current total by 10, add the next character's value, and move on. (You can make a larger or smaller map, change the number you multiply by at each step, and convert strings of any base you like.)
Integer to string is a longer process involving base conversion to 10. I suppose that since most integers have limited bits (32 or 64, usually), you know that it will come to a certain number of characters at most in a string (20?). So you can set up your own adder and iterate through each place for each bit after calculating its value (2^place).

Cell to Char in MATLAB doesn't work

I have used this code to read data from a plaintext file:
[race sex age namef] = textread('Fusion.txt', '%s %s %d %s');
I convert race from cell to char using: race = char(race); to do a string comparison (if(strcmp(race(k),'W')==1)) and it works as expected. I also need to namef to char but when I do, MATLAB returns 0 for every element of namef.
Here is a sample of my file:
W M 50 00001_930831_fb_a.ppm
W M 30 00002_930831_fa.ppm
W M 30 00002_930831_fb.ppm
W M 30 00002_931230_fa.ppm
W M 30 00002_931230_fb.ppm
W M 31 00002_940128_fa.ppm
W M 31 00002_940128_fb.ppm
Why is this happening?
From your question it is not clear whether conversion to char is necessary later on. For what you want to do, it is OK to compare to the individual elements of the cells race or namef:
strcmp(race{k}, 'W')
strcmp(named{k}, '00002_930831_fa.ppm')
Since strcmp operates on cell arrays of strings as well, you can also do things such as strcmp(race, 'W').
Since what you're doing should work fine, you're probably missing one thing: the last column in your file has multiple characters, so you need to access the whole row of the resulting string matrix, rather than a single element:
race = char(race); %// cell to character array of size [N,1]
namef = char(namef); %// cell to character array of size [N,M], padding added
for k=1:size(race,1)
condition_col1 = strcmp(race(k),'W')==1;
condition_col4 = strcmp(strtrim(namef(k,:)),'00002_930831_fa.ppm');
%// ... code goes here
end
If you use namef(k), you'll get the first character of each row, i.e. '0'. So namef(k,:) is my main point.
Also note that I added strtrim to the condition: turning to a character array will pad the fields to the length of the longest element (since matrices have to be rectangular).

Resources