Wikipedia: Filozofia!


26

Ponieważ wielu maniaków może wiedzieć, że większość stron (jak sądzę 95%) na Wikipedii ostatecznie prowadzi do filozofii:

Kliknij pierwszy link nie kursywą lub w nawiasach, który prowadzi do innego normalnego artykułu: (tzn. Nie Plik: lub Specjalny :, ale takie rzeczy jak Wikipedia: są w porządku) i powtarzaj to, dopóki nie osiągniesz filozofii.

Skrypt musi:

  • Weź pierwszą stronę jako dane wejściowe
  • Wydrukuj nazwę każdego artykułu, do którego trafi
  • I wydrukuj, ile artykułów zajęło dotarcie do filozofii, a jeśli tak nie było.

Zaczynasz z 1000 punktów i tracisz po jednym dla każdej postaci w kodzie, Punkty bonusowe za:

Wykrywanie zapętlonych artykułów i zatrzymywanie: +50

Wykrywanie zapętlonych artykułów i pytanie, czy użytkownik powinien przejść do następnego linku do artykułu: +170

Zezwalanie na domyślną poprzednią kontrolę jako argument wiersza polecenia lub podobny: +140

Najwyższy wynik wygrywa.


7
+1, wielkie wyzwanie! Wykrywanie nawiasów jest trudne: P
Klamka

1
Mam wrażenie, że przydałoby się trochę lepszej definicji, ale nie jestem jeszcze pewien, jak to zrobić.
Iszi

3
Stracić jeden punkt za każdy wpisany znak. Hmm Świetnie, rozumiem, po prostu skopiuję-wkleję postacie! Brak punktów straconych!
Justin

5
Nie zmieniaj zasad po opublikowaniu odpowiedzi; to dość niegrzeczne i ogólnie źle się czuje w społeczności tutaj ...
Klamka

Odpowiedzi:


8

Rubinowy, 1000 - 303 299 337 - 50 373 - 170 382 - 170 - 140 379 - 170 - 140 znaków = 697 701 713 7979 928 931

Jestem pewien, że należy wprowadzić wiele ulepszeń.

(Wymaga to Nokogiri)

require'open-uri'
require'nokogiri'
x="/wiki/"+gets.chomp
r=[n=i=0]
until x=~/\/Philosophy/
d=Nokogiri.HTML open"http://en.wikipedia.org#{x}"
x=d.css('p a').select{|a|t=a.xpath('preceding::text()').map(&:text)*'';t.count('(')==t.count(')')&&a.attr('href')=~/^.wiki[^:]+$/}[i].attr'href'
i=0
puts r.index(x)?"#{$><<'i=';i=($*[0]||gets).to_i;''}": r.push(x)[-1][6..-1]
n+=1
end
p n

Przykładowy przebieg:

c:\a\ruby>wikipedia_crawl_philosophy
Latin (note: this is my input)
Classical_antiquity
History
Umbrella_term
Terminology
Word
Linguistics
Science
Knowledge
Fact
Proof_(truth)
Argument
Logic
Reasoning
Consciousness
Quality_(philosophy)
Property_(philosophy)
Modern_philosophy
Philosophy
18

Przykładowy, w którym musiałem przejść do innego linku

c:\a\ruby>wikipedia_crawl_philosophy
Snow
Precipitation_(meteorology)
Meteorology
Atmospheric_physics
Synoptic_scale_meteorology
i=2 // I put the 0-indexed number of the link I wanted to go to (so, the third link)

Weather
Atmosphere
Gas
State_of_matter#The_four_fundamental_states
Physics
Natural_science
Sciences
Knowledge
Fact
Proof_(truth)
Argument
Logic
Reasoning
Consciousness
Quality_(philosophy)
Property_(philosophy)
Modern_philosophy
Philosophy
25

Sztuczki, których użyłem:

  • Użyłem selektora, p aaby uzyskać tylko linki nie kursywą, ponieważ wszystkie linki w rzeczywistym artykule, które nie są kursywą, zawsze znajdują się w elementach akapitu w Wikipedii.

hmmm ... może powinienem zabronienie ale Biblioteki, które pochodzą z języka ...
AlphaModder

@ user1825860 W rzeczywistości nie jest to biblioteka dostarczana z językiem; to klejnot. Zredagowałem swoją odpowiedź. Ale tak naprawdę chcesz podjąć to i tak trudne wyzwanie i zmusić nas do niestosowania bibliotek parsujących HTML? : P
Klamka

nie przejmuję się tym, ale tracisz punkty: P
AlphaModder

Powinieneś ponownie przeczytać pierwszy post i odpowiednio go edytować: P
AlphaModder

2
@ user1825860 Nie zmieniaj reguł po opublikowaniu odpowiedzi; to dość niegrzeczne ...
Klamka

5

„BASH ” - (jeśli się nie myli: 1000 - 397 + 170 + 140 = 913 punktów)
„BASH” - (jeśli się nie myli: 1000 - 386 + 170 + 140 = 924 punktów)

„BASH” - (jeśli się nie myli: 1000 - 381 + 170 + 140 = 929 punktów)

BASH jest celowo cytowany, ponieważ jest to mieszanka narzędzi używanych w powłokach * nix, ale zawartych w skrypcie bash.

Edycja 1:

  • Usunięte http://jako curldomyślne.
  • Zmieniono href=dopasowanie kotwic na f=as <a>, które nie mają żadnych innych normalnych atrybutów kończących się na f. (Istnieje możliwość niestandardowych tagów. Jak dotąd nie widziałem.)
  • !PhilZamiast tego ustaw komunikat wyjścia na „nie znaleziono ” NoPhil. Ten jest nieco ekscentryczne, jak można by też powiedzieć, na przykład !, 0, N, !Plub podobny.
  • Dziwne dwa: -swł. curlMożna usunąć, aby zmniejszyć o kolejne trzy bajty, ale to dałoby bałagan. Nie jestem pewien, czy to jest problem.
  • Zaktualizowana pomoc na tej stronie.

Używając dziwactw, kod kończy się na 379 bajtach, 931 punktach.

Mogłem również wdrożyć @plannapus wykorzystanie dopasowującego (miejmy nadzieję) oknie nawigacji dodając (p|ul).*?<(\1)dodając sześć bajtów (odjęcie sześciu punktów).

Edycja 2:

Używanie ${#c[@]}do drukowania stopni separacji zamiast $ilicznika.

Używając dziwactw, kod kończy się na 374 bajtach, 936 punktach.


Wzywam Cthulhu i szukam rozwiązania regexp + bash / shell / * nix.

Skradziony:

Wdrożone:

  • Wykryj pętlę i zapytaj, czy należy pobrać następny link.
  • Opcjonalnie wybierz następny link na duplikacie jako opcję.

Wymagania:

  • bash v.?
  • grepz -Pobsługą (PCRE).
  • sed
  • curl
  • cut

Stosowanie:

script PATH [OPTIONS]

Print separation of article from ``PATH'' to ``Philosophy'' on Wikipedia.
Degrees of separation, if found, is printed as last line. 
If not found last line yields ``!Phil''.

PATH    
     Absolute path to starting article, e.g: /wiki/Word 
OPTIONS
     y   Automatically select next link if already visited.
     n   (Or other) Quit if next link already visited.
BUGS
     1. On previous visit; "next link" is not checked. Thus if next link
     has already been visited we get eternal loop. Not sure if this
     disqualify +170 points.
     2. Sure there are.

Kod wewnętrzny Skopiuj do pliku. chmod +x filename. Uruchom ./script /wiki/…z powłoki bash.

u=($1);c=($1);while ! [[ "$u" =~ /Philosophy$ ]];do echo "$u";u=($(curl -s "en.wikipedia.org$u"|tr '\n' ' '|grep -Po '<p>.*?</p>'|sed 's/>[^<]*([^)]*)//g'|grep -o '<a [^>]*f="/wiki/[^":]*"'|cut -d\" -f2));for x in "${c[@]}";do if [ "$x" = "$u" ];then [ $2 ] &&s=$2||read -p "${u[0]}?" s;[ $s = y ] &&u[0]=${u[1]}||{ echo "!Phil";exit;} fi;done;c=("${c[@]}" "$u");done;echo ${#c[@]};

Rozszerzony i wyjaśniony kod:

u=($1); # Array of paths.
c=($1); # Array of visited paths.
# While $u != /Philosophy, ugly trick is to use $u instead of ${u[0]}.
while ! [[ "$u" =~ /Philosophy$ ]];do   
        echo "$u";      # Print current page.
        # curl   : prints retreived page to stdout. "-s" could be skipped.
        # tr     : replace all newline with space. This is a ®sanity thing when it comes to 
        #          twidling with html using regex.
        # grep 1 : match <p> tags. Using -P's ungreedy *?.
        # sed    : remove all occurences of "(" something ")".
        # grep 2 : match links where "href" attribute starts with /wiki/ and is not e.g. File:
        # cut    : match actual href value.
        # Result is added to array ``u''.
        u=($(curl -s "en.wikipedia.org$u" |
                tr '\n' ' ' | 
                grep -Po '<p>.*?</p>' | 
                sed 's/>[^<]*([^)]*)//g' | 
                grep -o '<a [^>]*f="/wiki/[^":]*"' | 
                cut -d\" -f2));

        # For previously visited pages as x.
        for x in "${c[@]}"; do 
                # If x equals to first page ...
                if [ "$x" = "$u" ]; then        
                        # Use option or ask.
                        [ $2 ] && s=$2 || read -p "${u[0]}?" s; 
                        # If response is "y" use next link, else exit with status.
                        [ $s = y ] && u[0]=${u[1]} || { 
                                echo "!Phil"; 
                                exit;
                        } 
                fi;
        done;
        # Append current link to "visited"
        c=("${c[@]}" "$u"); 
done;
# Print number of visited pages.
echo ${#c[@]}

Cholera, pokonałeś mnie o jeden punkt! : P Będę musiał bardziej
pograć w

Ye;), ale nie jestem pewien, czy to poprawny kod. Korzystanie z narzędzi w ten sposób.
Runium

5

JavaScript 726 (444 znaków [556] + 170)

Teraz doceniam to, że może to nie być poprawne jako skryptozakładka, ale i tak mi się podobało.

Sposób użycia: Przejdź do strony, od której chcesz zacząć, i uruchom następujące polecenie w konsoli:

(function(a){c=0,o="";$(u="html")[u](f=$('<iframe src="'+location+'?">').on("load",function(){$=f.contentWindow.$;p=f.contentDocument.title[s="split"](" - ")[0];c++;p=="Philosophy"?document.write("<pre>"+o+p+"\n"+c):(i=RegExp("^"+p+"$","m").test(o)?a||confirm("Loop, try next?")?2:0:1)&&(f.src=$("p>a").filter(function(){return(t=$(this).parent()[u]()[s](this.outerHTML)[0])[s]("(").length==t[s](")").length})[--i].href);o+=p+"\n"})[0])})(true)

W przypadku JavaScript dane wyjściowe są następujące:

JavaScript
Interpreter (computing)
Computer science
Science
Knowledge
Fact
Proof (truth)
Argument
Logic
Reason
Consciousness
Quality (philosophy)
Property (philosophy)
Modern philosophy
Philosophy
15

To rozwiązanie zakłada, że ​​chcesz przejść do następnego łącza w wykrywanej pętli, ale jeśli zmienisz truena końcu, falsepojawi się okno potwierdzenia (dość irytujące ...), nie jestem pewien, czy to kwalifikuje się do dodatkowa premia czy nie. Zakładam, że nie.

Zębaty:

(function(l){
    c=0,o='';
    $(u='html')[u](f=$('<iframe src="'+location+'?">').on('load',function(){ // Firefox needs the ? to properly load the frame
        $=f.contentWindow.$; // reference repeated calls as strings to save more bytes
        p=f.contentDocument.title[s='split'](' - ')[0]; // get the title

        c++;
        p=='Philosophy'?
            document.write('<pre>'+o+p+'\n'+c): // pre for nice formatting
            (i=RegExp('^'+p+'$','m').test(o)?
                l||confirm('Loop, try next?')?
                    2: // desired index + 1 so we can use as a boolean
                    0
                :
                1)&&
            (f.src=$('p>a').filter(function(){
                return (t=$(this).parent()[u]()[s](this.outerHTML)[0])[s]('(').length == t[s](')').length // shorter, but still not overly happy with this...
            })[--i].href);
            o+=p+'\n' // update output
    })[0])
})(true) // change this to show confirm box when loop detected

Więc początkowo brakowało mi części o ignorowaniu przedmiotów w parenach, dodając, że to sprawiło, że stało się to znacznie bardziej skomplikowane, więc mam nadzieję, że zagram w tę funkcję filtra (lub mam nadzieję, że całkowicie ją zastąpię).

Działa zarówno w Chrome, jak i Firefox (testowane w Firefox 26)


2
Wygląda niesamowicie, ale kończy się niepowodzeniem w przeglądarce Firefox 20.
stoisko

Argghh! Testowałem tylko Chrome. Przyjrzę się temu!
Dom Hastings

@boothby Powinien już działać w Firefoksie ... Nadal chcę pracować nad linkami, które wybrałem!
Dom Hastings,

5

C # - 813 znaków

Wynik: 1000-813 + 50 + 170 + 140 = 547 :(

Brak bibliotek zewnętrznych. Wykrywanie pętli .

Pierwszy argument to artykuł źródłowy, drugi to artykuł docelowy.

Wersja golfowa:

class Program
{
    static void Main(string[] a)
    {
        Func<XmlDocument,IList<string>> G=delegate(XmlDocument xd){return xd.SelectNodes("//p//a[starts-with(@href,'/wiki/') and not(contains(@href,':'))]").Cast<XmlNode>().Select(n=>n.Attributes["href"].InnerText).ToList();};Action<string> W=delegate(string s){Console.WriteLine(s);};var h=new HashSet<string>();var c=new WebClient();var x=new XmlDocument();var t=c.DownloadString(@"http://wikipedia.org/wiki/"+a[0]);int i=0,C=0;
    GO:
        x.LoadXml(t);var ns=G(x);
    COL:
        var f=ns[i];if(f.Equals("/wiki/"+a[1],StringComparison.OrdinalIgnoreCase)){goto END;}if(h.Contains(f)){W("loop: "+f);i++;goto COL;}else{h.Add(f);i=0;C++;}W(f);t=c.DownloadString(@"http://wikipedia.org"+f);goto GO;
    END:
        W("Found in "+C);
    }
}

Wersja zrozumiała:

class Program
{
    // arg[0] source article. arg[1] target article
    static void Main(string[] arg)
    {
        Func<XmlDocument, IList<string>> G = delegate(XmlDocument xd)
        {
            return xd.SelectNodes("//p//a[starts-with(@href,'/wiki/') and not(contains(@href,':'))]").Cast<XmlNode>().Select(n => n.Attributes["href"].InnerText).ToList();
        };
        Action<string> W = delegate(string s) { Console.WriteLine(s); };
        var h = new HashSet<string>(); var c = new WebClient(); var x = new XmlDocument();
        var allText = c.DownloadString(@"http://wikipedia.org/wiki/" + arg[0]);
        int i = 0; int C = 0;
    GO:
        x.LoadXml(allText);
        var ns = G(x);
    COL:
        var f = ns[i];
        if (f.Equals("/wiki/" + arg[1], StringComparison.OrdinalIgnoreCase))
        {
            goto END;
        }
        if (h.Contains(f))
        {
            W("loop: " + f); i++; goto COL;
        }
        else
        {
            h.Add(f); i = 0; C++;
        }
        W(f);
        allText = c.DownloadString(@"http://wikipedia.org" + f);
        goto GO;
    END:
        W("Found in " + C);
    }
}

Przykładowy przebieg, od „Sky” do „Philosophy”:

C:\>wiki.exe Sky Philosophy

/wiki/Earth
/wiki/Geometric_albedo
/wiki/Phase_angle_(astronomy)
/wiki/Observational_astronomy
/wiki/Astronomy
/wiki/Natural_science
/wiki/Sciences
/wiki/Latin_language
/wiki/Classical_antiquity
/wiki/History
/wiki/Ancient_Greek
/wiki/Greek_language
/wiki/Modern_Greek
loop: /wiki/Greek_language
/wiki/Colloquialism
/wiki/Word
/wiki/Linguistics
/wiki/Science
loop: /wiki/Latin_language
/wiki/Knowledge
/wiki/Fact
/wiki/Latin
loop: /wiki/Classical_antiquity
/wiki/Italic_languages
/wiki/Indo-European_languages
/wiki/Language_family
/wiki/Language
/wiki/Human
/wiki/Extinct
/wiki/Biology
loop: /wiki/Natural_science
/wiki/Life
loop: /wiki/Earth
/wiki/Physical_body
/wiki/Physics
loop: /wiki/Greek_language
loop: /wiki/Natural_science
/wiki/Matter
/wiki/Rest_mass
/wiki/Center_of_momentum_frame
loop: /wiki/Physics
/wiki/Inertial_frame
loop: /wiki/Physics
/wiki/Frame_of_reference
loop: /wiki/Physics
/wiki/Coordinate_system
/wiki/Geometry
loop: /wiki/Ancient_Greek
/wiki/Mathematics
/wiki/Quantity
/wiki/Property_(philosophy)
/wiki/Modern_philosophy
Found in 41

C:\>

5

Scala (294 znaków => 1000-294 + 140 = 846 punktów)

Zaktualizowane rozwiązanie, które automatycznie pobiera następny link, jeśli został już wykorzystany. Dzięki za 140 punktów bonusowych.

Logika: wybierz pierwszy link „/ wiki”, który nie zawiera „:” (więc ignoruje linki „Plik:”). Opłucz i powtórz z rekurencją zwracając liczbę + 1 za każdym razem. Trzymam pod ręką listę wszystkich poprzednich wyjść, więc program nie przechodzi w nieskończoną pętlę.

Wyrażenie regularne: Mam 2 formy wyrażenia regularnego.

  • "<p>.*?\"/wiki/([^:]*?)\".*?/p>"który znajduje linki w <p>tagach
  • "p>.*?/wiki/([^:]*?)\""który jest nieco bardziej eksperymentalnym tagiem, który okazał się działać, ale zapewnia różne wyniki, ponieważ czasami pobiera linki z paska informacyjnego po prawej stronie. Są to zwykłe artykuły, więc uważam, że nadal są aktualne. Jeśli okaże się, że tak nie jest, OP (lub ktoś inny) może zostawić mi komentarz, a ja mogę zaktualizować moje rozwiązanie do lepszego reg-ex.

Będę używać drugiego wyrażenia regularnego, dopóki nie znajdę przypadku testowego, w którym nie działa lub OP wspomina, że ​​zbieranie linków z paska bocznego jest niedozwolone (moim zdaniem paski informacyjne są nadal częścią sam artykuł; więcej streszczenia).


Zminimalizowane źródło:

object W extends App{print(x(Seq(args(0))));def x(s:Seq[Any]):Int={val? =s.last;println(?);?match{case "Philosophy"=>1;case _=>x(s:+"p>.*?/wiki/([^:]*?)\".*?/p>".r.findAllMatchIn(io.Source.fromURL("http://en.wikipedia.org/wiki/"+ ?).getLines.mkString).map(_ group 1).filter(!s.contains(_)).next)+1}}}

Czytelne źródło:

object W extends App {
  print(x(Seq(args(0))))

  def x(s: Seq[Any]): Int = {
    val ? = s.last
    println(?)
    ? match {
      case "Philosophy" => 1
      case _ => x(s :+ "p>.*?/wiki/([^:]*?)\"".r.findAllMatchIn(io.Source.fromURL("http://en.wikipedia.org/wiki/" + ?).getLines.mkString).map(_ group 1).filter(!s.contains(_)).next) + 1
    }
  }
}

Przykładowe dane wyjściowe:

Wkład

Space_toilet

Wydajność

Space_toilet
Weightlessness
G-force
Weight
Force
SI_unit
French_language
Second_language
Language_acquisition
Word
Linguistics
Science
Latin_language
Pontifical_Academy_for_Latin
Pope_Benedict_XVI
Pope_Benedict_(disambiguation)
Regnal_name#Catholic_Church
Monarch
State_(polity)
Community
Commutative_property
Mathematics
Quantity
Property_(philosophy)
Modern_philosophy
Philosophy
26

1
Scala nie wymaga głównego obiektu ani metody. Możesz uruchomić go za pomocą interpretera jako „scala <nazwa_pliku> [args ..]”. Użyj, args(0)aby uzyskać pierwszy argument, pozbyć się definicji objecti maindefinicji, i myślę, że możesz też usunąć :Int. pastebin.com/YqywKcG8
KChaloux

Okazuje się, że nie można usunąć : Int. Nie zdawałem sobie sprawy, że wykonujesz rekurencyjne połączenie. Również mój kod źródłowy został pobrany z twojego starego źródła czytelnego, ale obowiązują te same pojęcia.
KChaloux,

Spróbuję pozbyć się głównej metody. I tak, rekurencyjne połączenia zmusiły mnie do dodania :Inttam. Później dzisiaj dodam również czytelną formę rozwiązania 333 znaków, które mam. Dzięki za sugestie @KChaloux
javatarz

1
Tak jak powiedziałem, odwołanie do object Q extends App { ... }jest całkowicie niepotrzebne, jeśli uruchamiasz kod za pomocą interpretera, a nie kompiluje się ze skalacem. Po prostu biegnij zscala <filename> [args..]
KChaloux

4

R, 379 znaków; 1000-379 + 170 = 791 punktów

Wersja, która pyta użytkowników, jak postępować po wykryciu pętli

library(XML);w="http://en.wikipedia.org";W="/wiki/";n=1;A=c(scan(,""));while(A[n]!="Philosophy"){a=paste0(w,W,A[n]);d=sapply(strsplit(grep(W,sapply(xpathApply(xmlParse(readLines(a)),"//p/a[@href]|//ul/li/a[@href]",xmlAttrs),`[`,'href'),v=T),"/"),`[`,3);B=d[-grep(":",d)];n=n+1;if(B[1]%in%A)if(readline("Loop!2nd link?")=="n")break;A[n]=head(B[!B%in%A],1);cat(A[n],"\n")};cat(n-1)

Z wcięciami i komentarzami:

library(XML) #Uses package XML
w="http://en.wikipedia.org"
W="/wiki/"
n=1
A=c(scan(,"")) #Stdin + makes it a vector so we can store each iteration
while(A[n]!="Philosophy"){
    a=paste0(w,W,A[n])
    d=sapply(strsplit(grep(W,sapply( #The heart of the program
             xpathApply(xmlParse(readLines(a)),"//p/a[@href]|//ul/li/a[@href]",xmlAttrs),
             `[`,'href'),v=T),"/"),`[`,3)
    B=d[-grep(":",d)] #get rid of Templates, Files ,etc...
    n=n+1
    #Ask user if should proceed when loop encountered 
    #(any answer other than "n" is considered agreement):
    if(B[1]%in%A)if(readline("Loop!2nd link?")=="n")break
    A[n]=head(B[!B%in%A],1) #Take the first link that is not redundant
    cat(A[n],"\n")
    }
cat(n-1)

Przykładowy przebieg:

> library(XML);w="http://en.wikipedia.org";W="/wiki/";n=1;A=c(scan(,""));while(A[n]!="Philosophy"){a=paste(w,W,A[n],sep="");d=sapply(strsplit(grep(W,sapply(xpathApply(xmlParse(readLines(a)),"//p/a[@href]|//ul/li/a[@href]",xmlAttrs),`[`,'href'),v=T),"/"),`[`,3);B=d[-grep(":",d)];n=n+1;if(B[1]%in%A)if(readline("Loop!2nd link?")=="n")break;A[n]=head(B[!B%in%A],1);cat(A[n],"\n")};cat(n-1)
1: Extended_ASCII
2: 
Read 1 item
Eight-bit 
Computer_architecture 
Computer_science 
Science 
Logic 
List_of_aestheticians 
Art 
Human_behavior 
Behavior 
Organism 
Biology 
Loop!2nd link?y
Mathematics 
Quantity 
Property_(philosophy) 
Modern_philosophy 
Philosophy 
16

R, 325 znaków; ??? zwrotnica

Wersja, która domyślnie pobiera pierwsze nie redundantne łącze (tzn. Nie zapętla).

library(XML);w="http://en.wikipedia.org";W="/wiki/";n=1;A=c(scan(,""));while(A[n]!="Philosophy"){a=paste0(w,W,A[n]);d=sapply(strsplit(grep(W,sapply(xpathApply(xmlParse(readLines(a)),"//p/a[@href]|//ul/li/a[@href]",xmlAttrs),`[`,'href'),v=T),"/"),`[`,3);B=d[-grep(":",d)];n=n+1;A[n]=head(B[!B%in%A],1);cat(A[n],"\n")};cat(n-1)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.