Zadanie z matury 2018

Zadanie z matury 2018
Dobry Zawodnik
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 6 lat
  • Postów:14
0

Znajdź słowo, w którym występuje największa liczba różnych liter. Wypisz to słowo i liczbę
występujących w nim różnych liter. Jeśli słów o największej liczbie różnych liter jest więcej
niż jedno, wypisz pierwsze z nich pojawiające się w pliku z danymi.
Zrobilem takie cos i nie wiem co dalej:

Kopiuj
slowo=open("sygnaly.txt")
slownik={}
for znak in slowo:
    slownik[znak]=0
print(len(slownik))
KA
  • Rejestracja:ponad 6 lat
  • Ostatnio:4 dni
  • Lokalizacja:Warszawa
  • Postów:41
0
  1. W pliku są SŁOWA ODDZIELONE ZNAKIEM NOWEJ LINII, a nie jedno słowo :) (tu coś będzie o tym, jak to rozdzielić https://www.pythonforbeginners.com/dictionary/python-split)
  2. Potrzebujesz fora w forze.
Kopiuj
for slowo in slowa:
        znaki_w_slowie = Set()
        for znak in list(slowo):
            znaki_w_slowie.add(znak)

Set zawiera tylko unikalne elementy, więc liczba unikalnych liter w słowie jest równa len(znaki_w_slowie)
Jeszcze kilka poprawek i gotowe :)

EDIT
W zasadzie to można tworzyć Set z list, więc równie dobrze można zrobić znaki_w_slowie = Set(list(slowo)) i drugi for nie jest potrzebny.

edytowany 2x, ostatnio: kamillapinski
grski
@kamillapinski: sam str wystarczy, nie trzeba z niego robić listy, bo str też jest iterowalne :) więc set(slowo) będzie szybsze w tym wypadku
Dobry Zawodnik
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 6 lat
  • Postów:14
0

czyli do mojego kodu mam dopisać twój czy cały mój mam usunąć ?

grski
  • Rejestracja:ponad 9 lat
  • Ostatnio:8 miesięcy
  • Postów:245
0
Kopiuj
result = {'word': '', 'unique_chars': 0}
with open('xd') as f:
    for line in f:
        word = line.strip().lower()
        unique_chars = len(set(word))
        if result['unique_chars'] < unique_chars: result = {'word': word, 'unique_chars': unique_chars}
print(f"{result['word']} {result['unique_chars']}")

Tłumaczenie tego co robimy:

  1. otwieramy plik f jako context - tak by nie musieć ręcznie robić .close()
  2. jako f otworzony nam został dany plik, oraz przekształcony w iterabla, po którym możemy iterować - iterowanie po nim spowoduje wczytywanie linijka po linijce - to robimy za pomocą pętli for
  3. jako word zapisujemy sobie daną linię (bo jedno słowo jest na linijkę) i usuwamy z niego białe znaki, znaki końca linii itd. metodą strip()
  4. potem tworzymy zmienną unique_chars, która będzie równa długości seta z danego słowa, set() to nic innego jak zbiór unikalnych elemntów z danego iterabla, a stringi w pythonie są iterowalne, więc nie musimy castować na listę czy coś innego
  5. jeśli długość obecnego słowa - unique_chars jest większa od długości zapisanej w rezultacie, to wtedy uaktualniamy rezultat. Dzięki temu, że mamy tu < a nie <= to rezultat zostanie pierwszym jesli póxniej napotkamy inne słowa z taką samą liczbą znaków.
    6, wyprintowujemy wynik

Można całość jeszcze skrócić jeśli nie dbmay o czytelność a tylko o LOC:

Kopiuj
result = {'word': '', 'unique_chars': 0}
with open('xd') as f:
    for line in f:
           if  result['unique_chars'] < len(set(line.strip().lower())): result = {'word': line.strip().lower(), 'unique_chars': len(set(line.strip()))}

Edit - nie wiem, czy A i a są tutaj traktowane jako różne litery, ale jeśli tak, to trzeba wyrzucić .lower()


Napisałem książkę - Programowanie z Górskim: Junior Python Developer
Pora na następny krok na drodze po pierwszą pracę w it i WCALE-NIE-MITYCZNE #programista40k? Zapraszam.
edytowany 3x, ostatnio: grski
enedil
  • Rejestracja:ponad 11 lat
  • Ostatnio:3 dni
  • Postów:1027
2

A dla leniwych (jak akurat lubią tracić mało czasu w trakcie matury), oto szybkie rozwiązanie:

Kopiuj
with open("sygnaly.txt") as f:
    lines = f.read().splitlines()
    m = max(lines, key=lambda s: len(set(s)))
    print(m, len(set(m)))

Edit: wersja używająca mniej dodatkowej pamięci:

Kopiuj
with open("sygnaly.txt") as f:
    m = max(f, key=lambda s: len(set(s)))
    print(m, len(set(m)))
edytowany 5x, ostatnio: enedil
Zobacz pozostałe 2 komentarze
grski
@enedil zgadza się jest liniowe jeśli chodzi o pamięć/czas wykonania, ale w praktyce ładujesz całość pliku do pamięci, przy większym pliku nie jest to zbyt dobre rozwiązanie a no i tego read().splitlines() można by chyba zastąpić readlines()
enedil
@grski: istotnie, z taką zmianą, pamięć będzie maksymalnie liniowa względem najdłuższego słowa.
grski
@enedil nope, .readlines() też ci załaduje do pamięci plik cały :) to jest po prostu krótsza forma zapisu: read().splitlines() jak checsz mieć lazy generator to zamiast f.readlines() wystarczy po prostu... max(f, ...) :)
enedil
Masz rację. Ja natomiast użyłem tej pierwszej metody, gdyż od czasu do czasu przeszkadzał mi pusty element na końcu listy (bo w końcu pliki zwykły kończyć się znakiem końca linii).
Guaz
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:Częstochowa
  • Postów:221
0

Zaproponuje swoje rozwiązanie jakby ktoś dociekliwy robił test szybkości z jakimś dużym słownikiem :).

Kopiuj
best = ("",0)
with open("sygnaly.txt") as f:
    for line in f:
        tmp_len = len(set(line))
        if tmp_len > best[1]:
            best = (line, tmp_len)
print(*best)

Linux Mint
Arduino / Python 3.5.2
edytowany 1x, ostatnio: Guaz
AF
Kontynuując ciekawostkę. W przypadku dłuższych słowników możemy dokonać dalszej optymalizacji np. dodając linijkę if best[1]>=len(line): continue . Jeżeli nasze słowo nie jest dłuższe od naszego obecnego best to na pewno nie będzie miało więcej unikalnych znaków. Unikamy wywoływania set() dla każdego słowa - dla słownika 3000 angielskich losowych słow zwiększa to wydajność 2x. Albo posortować słowa od największych i przerwać pętlę w momencie kiedy len(line)<=best[1]. Również 2x szybciej. Ale takie ulepszenia to już sztuka dla sztuki w tym momencie :)
Guaz
Fakt, w sumie na to nie wpadłem, a z ciekawości sprawdzałeś może jak wypadają rozwiązania innych?
AF
W sumie to nie ale napisałrem na szybko benchmark, najpierw plik z 100k słowami potem z 10 milionami. Dla mniejszych słowników czasy są identycznie niskie 100K: Grski 93.782 ms Enedil 93.749 ms Guaz 93.752 ms Guaz_skipShorter 46.84 ms SortAndBreakOnShorter 62.163 ms mapToSetAndMax 78.119 ms -> po prostu max(map(set, f), len=key) 10M: Grski 984 ms Enedil 928 ms Guaz 875 ms Guaz_skipShorter 437 ms SortAndBreakOnShorter 593 ms mapToSetAndMax 806 ms Więc wszystkie rozwiązania maja bardzo dobre czasy.
Guaz
Faktycznie, różnica niewielka, myślałem że będą większe różnice ^^. Dzięki za zaspokojenie ciekawości :)
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)