Python - Kalkulator 998, SPOJ, optymalizacja

0

Witam.
Są trzy osoby, które mają zaliczone to zadanie w Pythonie 3.4, więc się da. Odpowiedź mam dobrą, jednak ciągle przekraczam czas. Oto treść:

Napisz program, który działa jak prosty kalkulator z pamięcią obsługujący pięć operacji: dodawanie, odejmowanie, mnożenie, dzielenie i obliczanie reszty z dzielenia liczb całkowitych. Przyjmujemy, że nasz kalkulator ma w pamięci 10 rejestrów o numerach 0 - 9 oraz że wszystkie rejestry zawierają na początku zera.

Wejście

Na wejście programu podana zostanie pewna nieokreślona liczba zestawów danych. Zestawy składają się z jednoznakowego symbolu operacji do wykonania (+, -, *, /, % i z) oraz następujących po nim dwóch liczb całkowitych.

Wyjście

Na wyjściu programu ma się pojawić ciąg liczb będących rezultatem wykonania pojawiających się na wejściu poleceń. Poszczególne liczby należy rozdzielić znakami nowej linii. To, co należy wykonać, zależy od symbolu operacji. Symbole +, -, *, / i % nakazują wykonanie odpowiednio dodawania, odejmowania, mnożenia, dzielenia i obliczenia reszty z dzielenia liczb, które są przechowywane w rejestrach o podanych numerach. Symbol z nakazuje zapis wartości podanej jako drugi argument w rejestrze o numerze podanym jako pierwszy argument. (Po wykonaniu tej operacji nie trzeba nic wyświetlać). Uwaga! Można założyć, że dane wejściowe nie zawierają polecenia dzielenia przez 0.

Przykład

Wejście:
z 3 6
z 1 89
z 2 60
z 0 11
+ 0 1
- 1 2
* 2 3
/ 3 0
% 3 1

Wyjście:
100
29
360
0
6 

Mój kod:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

rejestry = [0]*10
line = ""

try:
    line = input()
except EOFError:
    pass

# Empty sequences are false
while line:

    if line[0] == 'z':
        i = 4
        second = 0 # Length of second argument 
        while i < len(line):
            i += 1
            second += 1
        rejestry[int(line[2])] = int(line[4:4+second])

    elif line[0] == '+':
        a = int(rejestry[int(line[2])])
        b = int(rejestry[int(line[4])])
        print (str(a + b))
    elif line[0] == '-':
        a = int(rejestry[int(line[2])])
        b = int(rejestry[int(line[4])])
        print (str(a - b))
    elif line[0] == '*':
        a = int(rejestry[int(line[2])])
        b = int(rejestry[int(line[4])])
        print (str(a * b))
    elif line[0] == '/':
        a = int(rejestry[int(line[2])])
        b = int(rejestry[int(line[4])])
        print (str(int(a / b)))
    elif line[0] == '%':
        a = int(rejestry[int(line[2])])
        b = int(rejestry[int(line[4])])
        print (str(a % b))

    try:
        line = input()
    except EOFError:
        pass
 

Jakieś porady jak jeszcze bardziej można przyspieszyć ten algorytm?

0

Hej,
Tak na szybko co mi przychodzi do głowy to można by zamienić listy na tuple, które zajmują mniej pamięci chyba lista 32 a tupla 24. Jest to jakaś optymalizacja, chociaż nie wiem jak w kwestii funkcjonalnej. No i jeszcze te elify wyglądają słabo. Może po prostu w przypadku wykrycia znaku arytmetycznego tudzież dopasowania, przerywać i wychodzić z 'if', nie sprawdzając pozostałych warunków.

Pozdr

1

o_O

  1. Możesz mi wyjaśnić co to jest:
        while i < len(line):
            i += 1
            second += 1

? I dlaczego nie robisz zwyczajnie line.split()? Zresztą możesz równie dobrze zrobić przepisanie stringa do końca przez line[4:]
2. Cały czas konkwertujesz string->int, int->string. Po co? Skoro wkładasz do rejestu inta to inta odczytasz, nie trzeba konwersji!
3. Szybsze będzie wypisanie całego wyjścia na koniec niż printowanie po jednym.

2

Przekombinowałeś, prostszy kod na 0.01 s

# -*- coding: utf-8 -*-
import sys

debug = False
if len(sys.argv) > 1:
	debug = True


def main():
	tab = [0 for x in range(10)]
	for linia in sys.stdin:
		znak, l1, l2 = linia.split()
		l1, l2 = int(l1), int(l2)
		if debug is True:
			print(znak, l1, l2)
		if znak == "z":
			tab[l1] = l2
		if znak == "+":
			print(int(tab[l1] + tab[l2]))
		if znak == "-":
			print(int(tab[l1] - tab[l2]))
		if znak == "*":
			print(int(tab[l1] * tab[l2]))
		if znak == "/":
			print(int(tab[l1] / tab[l2]))
		if znak == "%":
			print(int(tab[l1] % tab[l2]))
	return

main()

a tu krótszy z tym samym czasem

# -*- coding: utf-8 -*-
import sys

debug = False
if len(sys.argv) > 1:
	debug = True


def main():
	tab = ['0' for x in range(10)]
	for linia in sys.stdin:
		znak, l1, l2 = linia.split()
		l1, l2 = int(l1), int(l2)
		if debug is True:
			print(znak, l1, l2)
		if znak == "z":
			tab[l1] = str(l2)
		else:
			print(int(eval(tab[l1] + znak + tab[l2])))
	return

main()

0

Ok, wielkie dzięki wszystkim, a zwłaszcza sigowi.

1 użytkowników online, w tym zalogowanych: 0, gości: 1