Jak uzyskać zmienna podana z klawiatury w petli while ?

0

Witajcie. Mam taki lamerski problem ponieważ próbuje uzyskać dostęp do zmiennej w pętli.
Chodzi o to, że robię zadanie ze SPOJ'a i nie mam podanych ilości testów na wstępie.
W c++ robiłem tak:
while(cin >> x) i wiadomo miałem dostęp do X;a a w pythonie robie tak :
while(str(raw_input())): - tylko że tutaj nie przypisuje tego do żadnej zmiennej. Jak odczytać tą wartośc z raw_input'a w pętli ?

Chyba że coś takiego by działało :

 
while 1:
     x = str(raw_input())
     if x == '': break
0
while 1:
 try:
  x=input()
  print -x
 except:break 
0

Edit:
Wkleiłem ten kod :


def Funky(stringi):
    x = len(stringi)
    if stringi[0] == stringi[x-1]:
        print 'TAK'
    else:
        print 'NIE'

ile = int(raw_input())
k = 1
while 1:
    strz = str(raw_input())
    if strz == '': break
    if k <= ile:
        Funky(strz)
    k=k+1
   
 

i wyskoczyło : błąd wykonania (NZEC) ... WTF?

Zadanie : http://pl.spoj.pl/problems/EQUIVCYC/

0

dzięki za odp :)

niestety nadal wywala mi błąd zadania pewnie coś źle robie

 
def Funky(stringi):
    x = len(stringi)
    if stringi[0] == stringi[x-1]:
        print 'TAK'
    else:
        print 'NIE'

ile = int(raw_input())
k = 1
while 1:
 try:
      strz = str(raw_input())
      if k <= ile:
          Funky(strz)
      k=k+1
 except: break 

Temat mozna usunac moze sobie poradze dalej ;D

0

Kilka luźnych uwag:

  • nie polecam korzystania z input (lub raw_input zależnie od wersji) oraz print, korzystaj bezpośrednio ze strumieni (sys.stdin i sys.stdout), szczególnie przy wypisywaniu, gdzie print powoduje flushowanie strumienia automatycznie, co tylko zajmuje czas
  • Python jest dynamicznie typowany, korzystaj z tego, nie rób zbędnych "rzutowań"
  • (niemal) wszystko można indeksować ujemnie, stąd x[len(x)-1] jest wolniejszą i mniej czytelną formą x[-1]
  • jeżeli już musisz pisać pętlę while w tej formie to nie używaj obsługi wyjątków, zbuduj poprawnie warunek w if i umieść tam break
  • staraj się trzymać typowego dla Pythona stylu, kod będzie znacznie czytelniejszy jeżeli źródło nie będzie mieszaniną wielu stylów
  • nie musisz zapamiętywać ilości zestawów, wejście ma gwarantowaną poprawność więc możesz po prostu po nim iterować bądź czytać do momentu otrzymania pustej linii
  • nie zrozumiałeś zadania, spójrz na pierwszy przykład, przesunięcie może być wielokrotne

Zadanie aż prosi się o rozwiązanie z użyciem coroutines, o dziwo mało znanego wśród programistów Pythona mechanizmu:

''' SPOJ 1537. EQUIVCYC z uzyciem coroutines, ofidyfil@4p 2011 '''
from sys import stdin, stdout


def equiv_cyc(str1, str2):
    ''' Sprawdzenie rownowaznosci cyklicznej. '''
    return len(str1) == len(str2) and str2 in str1 * 2

    
def tester(consumer):
    ''' Coroutine konsumujaca pary linii i produkujaca odpowiedz. '''
    while True:
        consumer('TAK\n' if equiv_cyc((yield), (yield)) else 'NIE\n')


def main():
    ''' Glowna funkcja programu, "karmiaca" coroutine `tester`. '''
    coroutine = tester(stdout.write)   # dalszym konsumentem bedzie `write`
    
    stdin.readline()                   # odrzucenie linii z iloscia wierszy
    coroutine.send(None)               # odpalenie coroutine
    
    for line in stdin:
        coroutine.send(line.rstrip())


if __name__ == '__main__':
    main()

Coroutines są przerywane w momencie napotkania yield, dopiero po "nakarmieniu" z użyciem send wykonywanie kodu jest wznawiane. W powyższym programie dopiero po wykonaniu dwóch kolejnych yield, tj. "nakarmieniu" dwiema kolejnymi liniami, następuje wykonanie warunku z equiv_cyc. Ze względu na specyfikę coroutines najpierw trzeba je odpalić wysyłając pustą wartość (w praktyce cokolwiek, pierwsza "wiadomość" powoduje wyłącznie wykonanie kodu przed yield).

0
ofidyfil napisał(a)

Kilka luźnych uwag:

  • nie polecam korzystania z input (lub raw_input zależnie od wersji) oraz print, korzystaj bezpośrednio ze strumieni (sys.stdin i sys.stdout), szczególnie przy wypisywaniu, gdzie print powoduje flushowanie strumienia automatycznie, co tylko zajmuje czas

Nie ma to większego znaczenia przy wejściu od użytkownika i wyjściu komunikatów.

ofidyfil napisał(a)
  • jeżeli już musisz pisać pętlę while w tej formie to nie używaj obsługi wyjątków, zbuduj poprawnie warunek w if i umieść tam break

Autor wątku chyba w ten sposób obsługuje wyjątek KeyboardInterrupt. Obsługa wyjątków jest zatem jak najbardziej na miejscu, ale nie koniecznie w taki sposób.

0

Przy wczytywaniu nie ma większych różnich. Wypisywanie to całkiem inna historia: z punktu widzenia programu i testów dane nie muszą być na bieżąco wysyłane w strumień, każde flushowanie bufora (a takie robie print) to tylko dodatkowy koszt, dodatkowy niepotrzebnie skonsumowany czas. write potrafi znacznie podnieść wydajność wypisywania chociaż oczywiście są lepsze, bardziej skomplikowane, sposoby.

Co się zaś tyczy łapania KeyboardInterrupt to zauważ, że @czupakabra wczytuje ilość zestawów i sprawdza, czy nie doszedł do końca, chociaż błędnie. Druga sprawa, że KeyboardInterrupt jest rzucane w momencie otrzymania Ctrl+C, czego w systemie testowym na pewno nie napotka, zaś na potrzeby sprawdzania programu u siebie łapać tego nie ma sensu. Użycie raw_input po dojściu do końca strumienia spowoduje rzucenie EOFError.

0

No tak. Nie doczytałem, że to ze SPOJa, a nie interaktywne dla usera. W takim razie raw_input() nie ma tutaj sensu. Ale tym bardziej nie ma sensu tuning wyjścia ;)
W ramach pokuty napisałem jednolinijkowca za karę:

import sys; print('\n'.join([ 'TAK' if (len(x[0]) == len(x[1]) and x[1] in x[0] * 2) else 'NIE' for x in [ (sys.stdin.readline().strip(), sys.stdin.readline().strip()) for y in xrange(int(sys.stdin.readline().strip())) ] ]))
0

Jeżeli zbuforujesz dane do pojedynczego wypisania to teoretycznie będzie to najszybsze, ale konkatencja stringów ma swój koszt, na potrzeby konkursu najlepiej byłoby eksperymentalnie ustalić w jakich zakresach danych konkretne rozwiązanie jest efektywniejsze. Co do jednolinijkowca to fajny, ale lepiej żebyś użył generatorów zamiast tablic. Kwestia zmiany [] na () (w argumencie join po prostu wykasowanie []) a zysk zauważalny: praktycznie brak dodatkowej alokacji i konstrukcji list, kolejne elementy są leniwie ewaluowane. Krotkę stringów można rozpakować w for, będzie szybsze i czytelniejsze niż wielokrotne indeksowanie. int nie wymaga stripniętego stringa, samo o to dba automatycznie, ew. można też się pokusić na zamianę strip na rstrip, odpadnie próba trymowania lewej strony stringa:

print '\n'.join('TAK' if len(x) == len(y) and y in x * 2 else 'NIE' for x, y in ((sys.stdin.readline().rstrip(), sys.stdin.readline().rstrip()) for n in xrange(int(sys.stdin.readline()))))

Dla picu można int(sys.stdin.readline()) zamienić na input() skoro to kod specyficzny dla Pythona 2.x, koszt jednorazowego evala liczby będzie niezauważalny:

print '\n'.join('TAK' if len(x) == len(y) and y in x * 2 else 'NIE' for x, y in ((sys.stdin.readline().rstrip(), sys.stdin.readline().rstrip()) for _ in xrange(input())))

Jedno z "poważniejszych" zastosowań Pythona to taka zabawa w udziwnianie jednolinijkowców ;]

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