python: read integer's from stream step by step - python

I can in Python:
n = int(input())
a = [int(x) for x in input().split()]
I can in c++:
int main()
{
int n, x;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> x;
somthing(x)
}
}
How to write it on Python (3.x)? Can I handle the numbers in the flow without saving all in list?
Input data (for example):
6
1 4 4 4 1 1
Can I use sys.stdin?
UPD:
Ok, I wrote this:
import sys
n = int(input())
i = 0
c = ""
s = ""
while i < n:
c = sys.stdin.read(1)
if c in [" ","\n"]:
x = int(s)
somthing(x)
s = ""
i += 1
else:
s += c
Is there a more elegant solution?

Python doesn't special-case such a specific form of input for you. By default, the input() function then reads a line from input (delimited by newline character) and converts it to a string.
You'll have to use the split() to separate the values.

Related

Why does this algorithm work so much faster in python than in C++?

I was reading "Algorithms in C++" by Robert Sedgewick and I was given this exercise: rewrite this weigted quick-union with path compression by halving algorithm in another programming language.
The algorithm is used to check if two objects are connected, for example for entry like 1 - 2, 2 - 3 and 1 - 3 first two entries create new connections whereas in the third entry 1 and 3 are already connected because 3 can be reached from 1: 1 - 2 - 3, so the third entry would not require creating a new connection.
Sorry if the algorithm description is not understandable, english is not my mother's tongue.
So here is the algorithm itself:
#include <iostream>
#include <ctime>
using namespace std;
static const int N {100000};
int main()
{
srand(time(NULL));
int i;
int j;
int id[N];
int sz[N]; // Stores tree sizes
int Ncount{}; // Counts the numbeer of new connections
int Mcount{}; // Counts the number of all attempted connections
for (i = 0; i < N; i++)
{
id[i] = i;
sz[i] = 1;
}
while (Ncount < N - 1)
{
i = rand() % N;
j = rand() % N;
for (; i != id[i]; i = id[i])
id[i] = id[id[i]];
for (; j != id[j]; j = id[j])
id[j] = id[id[j]];
Mcount++;
if (i == j) // Checks if i and j are connected
continue;
if (sz[i] < sz[j]) // Smaller tree will be
// connected to a bigger one
{
id[i] = j;
sz[j] += sz[i];
}
else
{
id[j] = i;
sz[i] += sz[j];
}
Ncount++;
}
cout << "Mcount: " << Mcount << endl;
cout << "Ncount: " << Ncount << endl;
return 0;
}
I know a tiny bit of python so I chose it for this exercise. This is what got:
import random
N = 100000
idList = list(range(0, N))
sz = [1] * N
Ncount = 0
Mcount = 0
while Ncount < N - 1:
i = random.randrange(0, N)
j = random.randrange(0, N)
while i is not idList[i]:
idList[i] = idList[idList[i]]
i = idList[i]
while j is not idList[j]:
idList[j] = idList[idList[j]]
j = idList[j]
Mcount += 1
if i is j:
continue
if sz[i] < sz[j]:
idList[i] = j
sz[j] += sz[i]
else:
idList[j] = i
sz[i] += sz[j]
Ncount += 1
print("Mcount: ", Mcount)
print("Ncount: ", Ncount)
But I stumbled upon this interesting nuance: when I set N to 100000 or more C++ version version appears to be a lot slower than the python one - it took about 10 seconds to complete the task for the algorithm in python whereas C++ version was doing it so slow I just had to shut it down.
So my question is: what is the cause of that? Does this happen because of the difference in rand() % N and random.randrange(0, N)? Or have I just done something wrong?
I'd be very grateful if someone could explain this to me, thanks in advance!
Those codes do different things.
You have to compare numbers in python with ==.
>>> x=100000
>>> y=100000
>>> x is y
False
There might be other problems, haven't checked. Have you compared the results of the apps?
As pointed out above the codes are not equivalent and especially when it comes to the use of is vs ==.
Look at the following Pyhton code:
while i is not idList[i]:
idList[i] = idList[idList[i]]
i = idList[i]
This is evaluated 0 or 1 times. Why?. Because if the while evaluates to True the 1st time, then i = idList[i] makes the condition True in the 2nd pass, because now i is for sure a number which is in idList
The equivalent c++
for (; i != id[i]; i = id[i])
id[i] = id[id[i]];
Here the code is checking against equality and not against presence and the number of times it runs it is not fixed to be 0 or 1
So yes ... using is vs == makes a huge difference because in Python you are testing instance equality and being contained in, rather than testing simple equality in the sense of equivalence.
The comparison of Python and C++ above is like comparing apples and pears.
Note: The short answer to the question would be: The Python version runs much faster because it is doing a lot less than the C++ version

Python equivalent to program in C

My goal is to translate the following written in C, into python, so I can evaluate the loop over a string of digits. Originally, the objective takes a range from 0 to 9, gathers input for each iteration while also multiplying, and sums the entire range. Last of all, determines the remainder after dividing by 11.
int checksum(char *str) {
int i, sum = 0;
for (i=0; i<9; i++) {
sum+= (str[i] - '0') * (i + 1);
}
return sum % 11;
}
A direct (but not very idiomatic) translation of the code would look as follows, notice that I renamed some of the variables to avoid clashes with Python's built-in functions:
def checksum(s):
c = 0
for i in range(9):
c += int(s[i]) * (i + 1)
return c % 11
Another more Pythonic option would be to use generator expressions instead of explicit loops:
def checksum(s):
return sum(int(e) * i for i, e in enumerate(s[:9], 1)) % 11

converting C code to Python by hand

Im am trying to covert the following C code to Python. I have no experience in C but a little in Python.
main( int argc, char *argv[])
{
char a[] = "ds dsf ds sd dsfas";
unsigned char c;
int d, j;
for(d = 0; d < 26; d++)
{
printf("d = %d: ", d);
for (j = 0; j < 21; j++ )
{
if( a[j] == ' ')
c = ' ';
else
{
c = a[j] + d;
if (c > 'z')
c = c - 26;
}
printf("%c", c);
}
printf("\n");
}
I have managed to up to this point: Where I get an list index out of range exception, any suggestions?
d=0
a=["ds dsf ds sd dsfas"]
while (d <26):
print("d = ",d)
d=d+1
j=0
while(j<21):
if a[j]=='':
c =''
else:
c = answer[j]+str(d)
if c>'z':
c=c-26
j=j+1
print("%c",c)
I hope this does what your C code is trying to achieve:
#! /usr/bin/python2.7
import string
a = 'ds dsf ds sd dsfas' #input
for d in range (26): #the 26 possible Caesar's cypher keys
shift = string.ascii_lowercase [d:] + string.ascii_lowercase [:d] #rotate the lower ase ascii with offset d
tt = string.maketrans (string.ascii_lowercase, shift) #convenience function to create a transformation, mapping each character to its encoded counterpart
print 'd = {}:'.format (d) #print out the key
print a.translate (tt) #translate the plain text and print it
the loop executes till j becomes 21.But I dont think you have that many elements in the a list. Thats why you get the error. I think len(a) is 18. So changing the loop as:
while j<len(a):
#code
or
while j<18:
#code
Will clear the error
See this, It's been explained with comments:
d=0
a=["ds dsf ds sd dsfas"]
# this will print 1 as a is a list object
# and it's length is 1 and a[0] is "ds dsf ds sd dsfas"
print len(a)
# and your rest of program is like this
while (d <26):
print("d = ",d)
d=d+1
#j=0
# while(j<21): it's wrong as list length is 1
# so it will give list index out of bound error
# in c array does not check for whether array's index is within
# range or not so it will not give out of bound error
for charValue in a:
if charValue is '':
c =''
else:
c = charValue +str(d) # here you did not initialized answer[i]
if c>'z':
c=c-26
#j=j+1
print("%c",c)

Need help porting C function to Python

I'm trying to port a C function which calculates a GPS checksum over to Python. According to the receiving end I am sometimes miscalculating the checksum, so must still have a bug in there.
C code is
void ComputeAsciiChecksum(unsigned char *data, unsigned int len,
unsigned char *p1, unsigned char *p2)
{
unsigned char c,h,l;
assert(Stack_Low());
c = 0;
while (len--) {
c ^= *data++;
}
h = (c>>4);
l = c & 0xf;
h += '0';
if (h > '9') {
h += 'A'-'9'-1;
}
l += '0';
if (l > '9') {
l += 'A'-'9'-1;
}
*p1 = h;
*p2 = l;
}
My attempt at a Python function is
def calcChecksum(line):
c = 0
i = 0
while i < len(line):
c ^= ord(line[i]) % 256
i += 1
return '%02X' % c;
Here is how you can set up a testing environment to diagnose your problem.
Copy the above C function to a file, remove the assert() line, and compile it to a shared library with
gcc -shared -o checksum.so checksum.c
(If you are on Windows or whatever, do the equivalent of the above.)
Copy this code to a Python file:
import ctypes
import random
c = ctypes.CDLL("./checksum.so")
c.ComputeAsciiChecksum.rettype = None
c.ComputeAsciiChecksum.argtypes = [ctypes.c_char_p, ctypes.c_uint,
ctypes.c_char_p, ctypes.c_char_p]
def compute_ascii_checksum_c(line):
p1 = ctypes.create_string_buffer(1)
p2 = ctypes.create_string_buffer(1)
c.ComputeAsciiChecksum(line, len(line), p1, p2)
return p1.value + p2.value
def compute_ascii_checksum_py(line):
c = 0
i = 0
while i < len(line):
c ^= ord(line[i]) % 256
i += 1
return '%02X' % c;
Now you have access to both versions of the checksum function and can compare the results. I wasn't able to find any differences.
(BTW, how are you computing the length of the string in C? If you are using strlen(), this would stop at NUL bytes.)
As a side note, your Python version isn't really idiomatic Python. Here are two more idiomatic versions:
def compute_ascii_checksum_py(line):
checksum = 0
for c in line:
checksum ^= ord(c)
return "%02X" % checksum
or
def compute_ascii_checksum_py(line):
return "%02X" % reduce(operator.xor, map(ord, line))
Note that these implementations should do exactly the same as yours.
Have you checked out this cookbook recipe? It hints at what input you should include in "line", returns a asterisk in front of the checksum, and gives one (input, output) data pair that you can use as test data.
Are you sure that "the receiver" is working correctly? Is the problem due to upper vs lower case hex letters?

Python String Overflow?

For some reason, the below results in an output of 0. I'm using a very large string (100,000 characters), and looking for a large integer, in the hundred billions, e.g 500,000,000,000. Is there something special I need to do? The goal is to find the number of sub-sequences of 1,2,3 in the first 100,000 digits of pi. I know the below is algorithmically correct. It's just not "code-correct."
pi100k = "3.14159[100,000 digits of pi]"
subSeqInit = 0
subSeqPair = 0
subSeqTotal = 0
for c in pi100k:
if c == 1:
subSeqInit = subSeqInit + 1
elif c == 2 and subSeqInit > 0:
subSeqPair = subSeqPair + 1
elif c == 3 and subSeqTotal > 0:
subSeqTotal = subSeqTotal + 1
print(subSeqTotal)
The simplest and fastest way is probably this:
subSeqTotal = pi100k.count("123")
pi100k = "3.14159[100,000 digits of pi]"
subSeqInit = 0
subSeqTotal = 0
for c in pi100k:
if c == '1':
subSeqInit = 1
elif c == '2' and subSeqInit == 1:
subSeqInit = 2
elif c == '3' and subSeqTotal == 2:
subSeqTotal = subSeqTotal + 1
subSeqInit = 0
print(subSeqTotal)
Python does not implicitly convert string characters to integers. Furthermore, your algorithm is not sound, what I have above will work better.
EDIT:
You could make this much shorter by using the regular expression module
import re
subSeqTotal = len(re.findall('123',pi100k))\
EDIT 2: As MRAB pointed out the best thing to use is pi100k.count('123')
It appears none of these solutions are correct. I don't think they search for the sub-sequence correctly.
I solved it recursively in C, with this algorithm:
/* global cstring for our pi data */
const char *g_numbers = 3.14........[100,000 digits];
/* global to hold our large total : some compilers don't support uint64_t */
uint64_t g_total = 0;
/* recursively compute the subsequnces of 1-2-3 */
void count_sequences(const char c, unsigned int index)
{
while (index < 100000){
switch (g_numbers[index]){
case '1': if (c == '1') count_sequences('2', index+1); break;
case '2': if (c == '2') count_sequences('3', index+1); break;
case '3':
if (c == '3'){
g_total++;
count_sequences('3', index+1);
return;
}
default: break;
}
index++;
}
}
Sorry I can't hand out the Python solution-- but I hope this helps. It shouldn't be too hard to re-work. I tried the given answers in Python and they didn't seem to work.

Categories