Przenoszenie średnia filtr kod java
Java SE 8: Lambda Szybki start W tym samouczku wprowadzono nowe wyrażenia lambda zawarte w platformie Java Platform Standard Edition 8 (Java SE 8). Czas do ukończenia Około 1 godziny Wprowadzenie Wyrażenia lambdy to nowa i ważna funkcja zawarta w Java SE 8. Zapewniają jasny i zwięzły sposób reprezentowania jednego interfejsu metody za pomocą wyrażenia. Wyrażenia Lambda ulepszają również biblioteki kolekcji, ułatwiając iterowanie, filtrowanie i wyodrębnianie danych z kolekcji. Ponadto nowe funkcje współbieżności zwiększają wydajność w środowiskach wielordzeniowych. Ten przykład Oracle (OBE) dostarcza wprowadzenia do wyrażeń lambda zawartych w Java SE 8. Wprowadzono wprowadzenie do anonimowych funkcji wewnętrznych, a następnie omówiono funkcjonalne interfejsy i nową składnię lambda. Następnie pokazano przykłady typowych wzorców użycia przed i po wyrażeniach lambda. W następnej sekcji omówiono typowy przypadek użycia wyszukiwania oraz sposób poprawienia kodu Java dzięki wprowadzeniu wyrażeń lambda. Ponadto niektóre z typowych interfejsów funkcjonalnych, predykatu i funkcji. dostarczone w java. util. function są wyświetlane w akcji. OBE kończy się przeglądem, w jaki sposób kolekcja Java została zaktualizowana za pomocą wyrażeń lambda. Dostarczony jest kod źródłowy wszystkich przykładów. Wymagania sprzętowe i programowe Poniżej znajduje się lista wymagań sprzętowych i programowych: Java Development Kit (JDK 8) wczesny dostęp do NetBeans 7.4 Wymagania wstępne Aby uruchomić te przykłady, musisz mieć wcześniejszą wersję JDK 8 i kopię NetBeans 7.4 lub nowszą wersję . Linki można znaleźć na głównej stronie Lambda. Dla Twojej wygody, tutaj są bezpośrednie linki. Uwaga: Kompilacje są dostępne dla wszystkich głównych systemów operacyjnych. To OBE zostało opracowane przy użyciu Linux Mint 13 (UbuntuDebian). Zainstaluj JDK8 i NetBeans zgodnie z instrukcjami dostarczonymi z pobranymi plikami. Dodaj do katalogu PATH katalogi bin dla Java i NetBeans. Uwaga: Ten dokument OBE został ostatnio zaktualizowany w grudniu 2017 r. Kontekst Anonimowa klasa wewnętrzna W języku Java anonimowe klasy wewnętrzne umożliwiają implementację klas, które mogą występować tylko raz w aplikacji. Na przykład w standardowej aplikacji Swing lub JavaFX wymagana jest liczba procedur obsługi zdarzeń dla zdarzeń klawiatury i myszy. Zamiast pisać oddzielną klasę obsługi zdarzeń dla każdego wydarzenia, możesz napisać coś takiego. W przeciwnym razie dla każdego zdarzenia wymagana jest osobna klasa implementująca ActionListener. Tworząc klasę tam, gdzie jest ona potrzebna, kod jest trochę łatwiejszy do odczytania. Kod nie jest elegancki, ponieważ wystarczy trochę kodu, aby zdefiniować jedną metodę. Interfejsy funkcjonalne Kod, który definiuje interfejs ActionListener, wygląda mniej więcej tak: Przykład ActionListener jest interfejsem tylko z jedną metodą. W języku Java SE 8 interfejs zgodny z tym wzorcem jest znany jako interfejs funkcjonalny. Uwaga: ten typ interfejsu. był wcześniej znany jako typ pojedynczej abstrakcyjnej metody (SAM). Korzystanie z funkcjonalnych interfejsów z anonimowymi klasami wewnętrznymi jest powszechnym wzorcem w Javie. Oprócz klas EventListener, interfejsy takie jak Runnable i Comparator są używane w podobny sposób. Dlatego interfejsy funkcjonalne są wykorzystywane do użycia z wyrażeniami lambda. Wyrażenia Lambda Składnia Wyrażenia Lambda odpowiadają na masowość anonimowych klas wewnętrznych, konwertując pięć linii kodu do pojedynczej instrukcji. To proste rozwiązanie horyzontalne rozwiązuje problem pionowy prezentowany przez klasy wewnętrzne. Wyrażenie lambda składa się z trzech części. Wprowadzenie do programowania w języku Java - Tutorial 5.1. Co to jest interfejs w Javie Interfejsy to typ podobny do klasy i jest definiowany za pomocą słowa kluczowego interfejsu. Interfejsy są używane do definiowania wspólnego zachowania implementujących klasy. Jeśli dwie klasy implementują ten sam interfejs, inny kod działający na poziomie interfejsu może korzystać z obiektów obu klas. Podobnie jak klasa interfejs definiuje metody. Klasy mogą implementować jeden lub kilka interfejsów. Klasa implementująca interfejs musi zapewniać implementację wszystkich abstrakcyjnych metod zdefiniowanych w interfejsie. 5.2. Abstrakcyjne, domyślne i statyczne metody w interfejsach Interfejs może mieć abstrakcyjne metody i domyślne metody. Domyślna metoda jest definiowana za pomocą domyślnego słowa kluczowego na początku sygnatury metody. Wszystkie inne metody zdefiniowane w interfejsie są publiczne, a abstrakcyjna jawna deklaracja tych modyfikatorów jest opcjonalna. Interfejsy mogą mieć stałe, które są zawsze niejawnie publiczne, statyczne i ostateczne. Poniższy kod pokazuje przykładową implementację interfejsu. Zmienna może być albo: prymitywną zmienną referencyjną zmiennej. Prymitywna zmienna zawiera wartość. Zmienna referencyjna zawiera odniesienie (wskaźnik) do obiektu. Dlatego jeśli porównamy dwie zmienne referencyjne, porównamy, czy oba wskazują na ten sam obiekt. Aby określić, czy obiekty zawierają te same dane, użyj wywołania metody object1.equals (object2). 7.2. Zmienna instancji zmiennej instancji jest powiązana z instancją klasy (zwaną również obiektem). Dostęp działa na tych obiektach. Zmienne instancji mogą mieć dowolną kontrolę dostępu i mogą być oznaczone jako ostateczne lub przejściowe. Zmiennych instancji oznaczonych jako ostateczne nie można zmienić po przypisaniu im wartości. 7.3. Zmienna lokalna Deklaracje zmiennych lokalnych (stos) nie mogą mieć modyfikatorów dostępu. Zmienne lokalne nie otrzymują wartości domyślnych, więc muszą zostać zainicjowane, zanim będą mogły zostać użyte. final jest jedynym modyfikatorem dostępnym dla zmiennych lokalnych. Ten modyfikator określa, że zmiennej nie można zmienić po pierwszym przypisaniu. 7.4. Metody Metoda jest blokiem kodu z parametrami i wartością zwracaną. Można go wywołać na obiekcie. Metody mogą być zadeklarowane za pomocą var-args. W tym przypadku metoda deklaruje parametr, który akceptuje wszystko od zera do wielu argumentów (składnia: nazwa typu 82308203). Metoda może mieć tylko jeden parametr var-args i musi to być ostatni parametr w metodzie. Zastąpienie metody nadklasy: metoda musi zawierać dokładnie ten sam parametr zwracany i te same argumenty. Również parametr return musi być taki sam. Metody przeciążania: Metoda przeciążona to metoda o tej samej nazwie, ale o różnych argumentach. Typu zwracanego nie można użyć do przeciążenia metody. 7.5. Metoda główna Publiczna metoda statyczna z następującym sygnaturą może być użyta do uruchomienia aplikacji Java. Taka metoda jest zwykle nazywana główną metodą. W poprzednim rozdziale wyjaśniono, jak utworzyć i skompilować program Java w wierszu poleceń. Zintegrowane środowisko programowania Java (IDE) zapewnia wiele łatwych w użyciu funkcji do tworzenia programów Java. Dostępne są inne bardzo silne IDE, na przykład Eclipse IDE. Informacje na temat korzystania z Eclipse IDE można znaleźć w samouczniku środowiska IDE Eclipse. W pozostałym opisie użyto frazy: Utwórz projekt Java o nazwie82308203. Odnosi się to do tworzenia projektu Java w środowisku Eclipse. Jeśli używasz innego IDE, wykonaj wymagane kroki w tym IDE. 13. Ćwiczenia - Tworzenie obiektów i metod Java 13.1. Utwórz klasę Person i uruchom instancję Utwórz nowy projekt Java o nazwie com. vogella. javastarter. exercises1 i pakiet o tej samej nazwie. Utwórz klasę o nazwie Osoba. Dodaj do niego trzy zmienne instancji, jedną do przechowywania imienia osoby, jedną do przechowywania nazwiska i jedną do przechowywania wieku Osoby. Użyj konstruktora obiektu Person, aby ustawić wartości na pewną wartość domyślną. Dodaj metodę toString opisaną przez następujące kodowanie i rozwiązaj TODO. Ta metoda służy do konwersji obiektu na reprezentację String. Utwórz nową klasę o nazwie Main z publicznym statycznym void main (String args). W tej metodzie utwórz instancję klasy Person. 13.2. Użyj konstruktora Dodaj konstruktor do swojej klasy Person, która przyjmuje imię, nazwisko i wiek jako parametr. Przypisz wartości do zmiennych instancji. W swojej głównej metodzie utwórz co najmniej jeden obiekt typu Person i użyj System. out. println () z obiektem jako parametrem. 13.3. Zdefiniuj metody getter i setter Zdefiniuj metody, które umożliwiają odczytanie wartości zmiennych instancji i ich ustawienie. Te metody nazywane są setter i getter. Polecenie getters powinno zaczynać się od polecenia get, po którym następuje nazwa zmiennej, w której pierwsza litera zmiennej jest zamieniana na wielką. Seter powinien zaczynać się od set, po którym następuje nazwa zmiennej, w której pierwsza litera zmiennej jest zamieniana na wielką. Na przykład zmienna o nazwie firstName ma metodę getFirstName () pobierającą i metodę ustawiającą setFirstName (String s). Zmień główną metodę, aby utworzyć jeden obiekt Person i użyj metody ustawiającej, aby zmienić nazwisko. 13.4. Utwórz obiekt Adres Utwórz nowy obiekt o nazwie Adres. Adres powinien umożliwiać zapisanie adresu osoby. Dodaj nową instancję zmiennej tego typu w obiekcie Person. Utwórz również program pobierający i ustawiający dla obiektu Adres w obiekcie Person. 14. Rozwiązanie - Tworzenie obiektów i metod Java Jeśli wywołasz metodę lub uzyskasz dostęp do obiektu, który nie został zainicjowany (null), otrzymasz wyjątek NullPointerException (NPE). Do uniknięcia tych NPE można użyć klasy java. util. Optional. java. util. Optional jest dobrym narzędziem do wskazania, że wartość zwracana może być nieobecna, co można zobaczyć bezpośrednio w sygnaturze metody, a nie tylko wspomnieć, że wartość pusta może zostać zwrócona w JavaDoc. Jeśli chcesz wywołać metodę na obiekcie opcjonalnym i sprawdzić właściwość, możesz użyć metody filtru. Metoda filtru przyjmuje predykat jako argument. Jeśli wartość jest obecna w obiekcie opcjonalnym i jest zgodna z predykatem, metoda filtru zwraca tę wartość w przeciwnym razie zwraca pusty obiekt opcjonalny. Możesz utworzyć Opcjonalnie na różne sposoby: Metoda ifPresent może być użyta do wykonania kodu na obiekcie, jeśli jest obecny. Załóżmy, że masz obiekt Todo i chcesz wywołać na nim metodę getId (). Możesz to zrobić za pomocą następującego kodu. Za pomocą metody mapy można przekształcić obiekt, jeśli jest obecny, oraz za pomocą metody filtrującej, którą można filtrować dla określonych wartości. Aby uzyskać rzeczywistą wartość opcji Opcjonalnie, można użyć metody get (). Ale w przypadku, gdy opcja Opcjonalna jest pusta, zostanie zgłoszony wyjątek NoSuchElementException. Aby uniknąć tego wyjątku NoSuchElementException, można użyć orElse lub orElseGet w celu zapewnienia wartości domyślnej w przypadku nieobecności. 22. Konwersja typów Jeśli używasz zmiennych różnych typów Java wymaga dla określonych typów jawnej konwersji. Poniżej podano przykłady tej konwersji. 22.1. Konwersja do ciągu Użyj poniższych, aby przekonwertować z innych typów na Ciągi 22.2. Konwersja z ciągu na numer Konwersja ciągu na numer jest niezależna od ustawień lokalnych, np. zawsze używa angielskiego powiadomienia o numerze. W tym powiadomieniu prawidłowy format liczb to 8,20. Niemiecki numer 8,20 spowodowałby błąd. Aby przekonwertować z niemieckiego numeru, musisz użyć klasy NumberFormat. Wyzwanie polega na tym, że gdy wartość wynosi na przykład 98,00, klasa NumberFormat utworzyłaby wartość Long, która nie może być rzutowana na Double. Stąd następująca złożona klasa konwersji. Wesprzyj bezpłatną treść Pytania i dyskusję Tutorial amp code license Uzyskaj kod źródłowy1.5 Input and Output W tym dziale rozszerzamy zbiór prostych abstrakcji (input-line input i standard output), które używamy jako interfejsu pomiędzy naszymi programami Java i świat zewnętrzny, aby uwzględnić standardowe wejście. standardowy rysunek. i standardowy dźwięk. Standardowe wejście ułatwia pisanie programów przetwarzających dowolne ilości danych wejściowych i interakcję z naszymi programami. Standardowe rysowanie pozwala nam pracować z grafiką, a standardowe audio dodaje dźwięk. Widok z lotu ptaka. Program Java pobiera wartości wejściowe z wiersza poleceń i wypisuje łańcuch znaków jako wynik. Domyślnie zarówno argumenty wiersza polecenia, jak i standardowe wyjście są powiązane z aplikacją, która przyjmuje polecenia, które nazywamy oknem terminala. Oto kilka instrukcji korzystania z wiersza poleceń w systemie. Mac middot Windows middot Linux Argumenty wiersza polecenia. Wszystkie nasze klasy mają metodę main (), która pobiera Argumenty łańcuchowe jako argument. Ta tablica jest sekwencją argumentów linii poleceń, które wpisujemy. Jeśli chcemy, aby argument był liczbą, musimy użyć metody takiej jak Integer. parseInt (), aby przekonwertować ją ze String do odpowiedniego typu. Standardowe wyjście. Aby wydrukować wartości wyjściowe w naszych programach, używamy System. out. println (). Java wysyła wyniki do abstrakcyjnego strumienia znaków znanego jako standardowe wyjście. Domyślnie system operacyjny łączy standardowe wyjście z oknem terminala. Całe wyjście w naszych programach do tej pory pojawiło się w oknie terminala. RandomSeq. java używa tego modelu: pobiera argument n linii poleceń i drukuje na standardowe wyjście sekwencję n liczb losowych od 0 do 1. Aby uzupełnić nasz model programowania, dodajemy następujące biblioteki: Standardowe wejście. Czytaj liczby i ciągi od użytkownika. Standardowy rysunek. Drukuj grafikę. Standardowy dźwięk. Utwórz dźwięk. Standardowe wyjście. Metody Java System. out. print () i System. out. println () implementują podstawowe standardowe wyjście, którego potrzebujemy. Niemniej jednak, aby traktować standardowe wejście i standardowe wyjście w jednolity sposób (i wprowadzić kilka usprawnień technicznych), używamy podobnych metod, które są zdefiniowane w naszej bibliotece StdOut: Java metody print () i println () to te, które masz używam. Metoda printf () daje nam większą kontrolę nad wyglądem wydruku. Sformatowane podstawy drukowania. W najprostszej postaci printf () przyjmuje dwa argumenty. Pierwszy argument nazywa się ciągiem formatującym. Zawiera specyfikację konwersji opisującą, w jaki sposób drugi argument ma zostać przekonwertowany na ciąg znaków wyjściowych. Łańcuchy formatowania zaczynają się i kończą od jednoliterowego kodu konwersji. Poniższa tabela podsumowuje najczęściej używane kody: Format string. Ciąg formatujący może zawierać znaki oprócz znaków specyfikacji konwersji. Specyfikacja konwersji zostaje zastąpiona wartością argumentu (przekształconą na określony łańcuch), a wszystkie pozostałe znaki są przekazywane do wyjścia. Wiele argumentów. Funkcja printf () może zająć więcej niż dwa argumenty. W takim przypadku ciąg formatu będzie miał dodatkową specyfikację konwersji dla każdego dodatkowego argumentu. Oto więcej dokumentacji na temat składni łańcuchowej formatu printf. Standardowe wejście. Nasza biblioteka StdIn pobiera dane ze standardowego strumienia wejściowego, który zawiera ciąg wartości rozdzielonych białymi znakami. Każda wartość jest ciągiem lub wartością z jednego z pierwotnych typów JEDNOSTEK. Jedną z kluczowych cech standardowego strumienia wejściowego jest to, że twój program pobiera wartości, gdy je czyta. Gdy program odczyta wartość, nie może wykonać kopii zapasowej i przeczytać go ponownie. Biblioteka jest definiowana za pomocą następującego interfejsu API: Obecnie rozważamy kilka przykładów. Wpisywanie danych wejściowych. Kiedy używasz polecenia java do wywołania programu Java z linii poleceń, faktycznie robisz trzy rzeczy: (1) wydawanie polecenia, aby rozpocząć wykonywanie twojego programu, (2) określanie wartości argumentów linii poleceń, oraz ( 3) rozpoczęcie definiowania standardowego strumienia wejściowego. Ciąg znaków, który wpisujesz w oknie terminala po linii poleceń, jest standardowym strumieniem wejściowym. Na przykład AddInts. java pobiera argument n linii poleceń. następnie odczytuje n liczb ze standardowego wejścia i dodaje je, a następnie wypisze wynik na standardowe wyjście: Format wejściowy. Jeśli wpiszesz abc lub 12.2 lub true, gdy StdIn. readInt () spodziewa się int. to odpowie z InputMismatchException. StdIn traktuje ciągi kolejnych białych znaków jako identyczne z jedną spacją i pozwala na ograniczenie liczb za pomocą takich ciągów. Interaktywne wejście użytkownika. TwentyQuestions. java to prosty przykład programu, który współdziała z jego użytkownikiem. Program generuje losową liczbę całkowitą, a następnie podaje wskazówki użytkownikowi próbującemu zgadnąć liczbę. Podstawową różnicą między tym programem a innymi, które napisaliśmy, jest to, że użytkownik ma możliwość zmiany przepływu sterowania podczas wykonywania programu. Przetwarzanie strumienia wejściowego o dowolnym rozmiarze. Zazwyczaj strumienie wejściowe są skończone: twój program przechodzi przez strumień wejściowy, zużywając wartości, dopóki strumień nie będzie pusty. Ale nie ma ograniczenia wielkości strumienia wejściowego. Average. java wczytuje sekwencję liczb rzeczywistych ze standardowego wejścia i drukuje ich średnią. Przekierowanie i orurowanie. W wielu aplikacjach wpisywanie danych wejściowych jako standardowego strumienia wejściowego z okna terminala jest nie do utrzymania, ponieważ ogranicza to moc przetwarzania naszych programów przez ilość danych, które możemy wpisać. Podobnie, często chcemy zapisać informacje wydrukowane na standardowym strumieniu wyjściowym do późniejszego wykorzystania. Możemy użyć mechanizmów systemu operacyjnego, aby rozwiązać oba problemy. Przekierowanie standardowego wyjścia do pliku. Dodając prostą dyrektywę do polecenia wywołującego program, możemy przekierować jego standardowe wyjście do pliku, albo do trwałego przechowywania, albo do wprowadzenia do innego programu w późniejszym czasie. Na przykład polecenie określa, że standardowy strumień wyjściowy nie ma być drukowany w oknie terminala, ale zamiast tego ma zostać zapisany w pliku tekstowym o nazwie data. txt. Każde wywołanie StdOut. print () lub StdOut. println () dołącza tekst na końcu tego pliku. W tym przykładzie końcowym wynikiem jest plik zawierający 1000 losowych wartości. Przekierowanie standardowego wyjścia z pliku. Podobnie możemy przekierować standardowe wejście, aby StdIn odczytał dane z pliku zamiast z okna terminala. Na przykład polecenie czyta sekwencję liczb z pliku data. txt i oblicza ich średnią wartość. W szczególności symbol lt jest dyrektywą implementującą standardowy strumień wejściowy przez odczytanie z pliku data. txt zamiast czekania, aż użytkownik wpisze coś w oknie terminala. Kiedy program wywołuje StdIn. readDouble (). system operacyjny odczytuje wartość z pliku. Ta możliwość przekierowania standardowego wejścia z pliku umożliwia nam przetwarzanie ogromnych ilości danych z dowolnego źródła za pomocą naszych programów, ograniczonych jedynie wielkością plików, które możemy przechowywać. Łączenie dwóch programów. Najbardziej elastycznym sposobem implementacji standardowych danych wejściowych i standardowych wyjść wyjściowych jest określenie, że są one implementowane przez nasze własne programy. Ten mechanizm nazywa się rurociągiem. Na przykład poniższe polecenie określa, że standardowe wyjście dla RandomSeq i standardowego strumienia wejściowego dla Average to ten sam strumień. Filtry. Dla wielu typowych zadań wygodnie jest myśleć o każdym programie jako o filtrze, który konwertuje standardowy strumień wejściowy do standardowego strumienia wyjściowego w pewien sposób, RangeFilter. java pobiera dwa argumenty wiersza poleceń i drukuje na standardowym wyjściu te liczby ze standardowego wejścia które mieszczą się w podanym zakresie. Twój system operacyjny zapewnia również wiele filtrów. Na przykład filtr sortowania umieszcza wiersze na standardowym wejściu w posortowanej kolejności: Kolejny przydatny filtr to więcej. który odczytuje dane ze standardowego wejścia i wyświetla je w oknie terminala po jednym ekranie na raz. Na przykład, jeśli wpiszesz, zobaczysz tyle liczb, ile zmieści się w oknie terminala, ale więcej będzie czekać na naciśnięcie spacji przed wyświetleniem każdego kolejnego ekranu. Standardowy rysunek. Teraz wprowadzamy prostą abstrakcję do tworzenia rysunków jako wynik. Wyobrażamy sobie abstrakcyjne urządzenie do rysowania zdolne do rysowania linii i punktów na dwuwymiarowym płótnie. Urządzenie jest w stanie reagować na polecenia, które nasze programy wydają w postaci wywołań statycznych metod w StdDraw. Główny interfejs składa się z dwóch rodzajów metod: poleceń rysowania, które powodują, że urządzenie podejmuje działanie (takie jak rysowanie linii lub rysowanie punktu) i steruje poleceniami, które określają parametry, takie jak rozmiar pisaka lub skala współrzędnych. Podstawowe polecenia rysowania. Najpierw rozważmy komendy rysowania: Te metody są prawie samopisujące się: StdDraw. line (x0, y0, x1, y1) rysuje segment prostoliniowy łączący punkt (x 0.y 0) z punktem (x 1. 1). StdDraw. point (x, y) rysuje punkt wyśrodkowany na punkcie (x. Y). Domyślną skalą współrzędnych jest kwadrat jednostki (wszystkie współrzędne xiy współrzędnych od 0 do 1). Standardowa implementacja wyświetla płótno w oknie na ekranie komputera, z czarnymi liniami i punktami na białym tle. Twój pierwszy rysunek. HelloWorld do programowania grafiki za pomocą StdDraw polega na narysowaniu trójkąta z punktem w środku. Triangle. java realizuje to za pomocą trzech wywołań do StdDraw. line () i jednego wywołania StdDraw. point (). Polecenia sterujące. Domyślny rozmiar płótna to 512 na 512 pikseli, a domyślny układ współrzędnych to kwadrat jednostki, ale często chcemy rysować wykresy w różnych skalach. Ponadto często chcemy rysować odcinki linii o różnej grubości lub punkty o różnej wielkości od standardu. Aby spełnić te potrzeby, StdDraw ma następujące metody: Na przykład sekwencja dwóch wywołań ustawia współrzędne rysunku w ramce ograniczającej, której lewy dolny róg znajduje się na (x 0.y 0), a którego prawy górny róg jest w (x 1. y 1). Filtrowanie danych do standardowego rysunku. PlotFilter. java odczytuje sekwencję punktów zdefiniowanych współrzędnymi (x. y) ze standardowego wejścia i rysuje punkt w każdym punkcie. Przyjmuje konwencję, że pierwsze cztery cyfry na standardowym wejściu określają obwiednię, aby mógł skalować wykres. Wykreślanie wykresu funkcji. FunctionGraph. java narysuje funkcję y sin (4 x) sin (20 x) w przedziale (0, pi). Istnieje nieskończona liczba punktów w przedziale, więc musimy zrobić z oceną funkcji w skończonej liczbie punktów w przedziale. Próbkujemy funkcji, wybierając zestaw wartości x, a następnie obliczając wartości y, oceniając funkcję przy każdej x-wartości. Wykreślanie funkcji przez łączenie kolejnych punktów z liniami tworzy tzw. Fragmentaryczną aproksymację liniową. Kontury i wypełnione kształty. StdDraw zawiera również metody rysowania okręgów, prostokątów i dowolnych wielokątów. Każdy kształt definiuje kontur. Gdy nazwa metody jest tylko nazwą kształtu, ten kontur jest śledzony przez pióro rysunkowe. Gdy nazwa metody zaczyna się od wypełnionej. nazwany kształt jest wypełniony bryłą, nie jest śledzony. Argumenty dla circle () definiują okrąg o promieniu r argumenty dla square () definiują kwadrat o długości boku 2r wyśrodkowany na danym punkcie i argumenty dla wielokąta () definiują sekwencja punktów, które łączymy liniami, w tym jeden od ostatniego punktu do pierwszego punktu. Tekst i kolor. Aby dodać lub zaznaczyć różne elementy na swoich rysunkach, StdDraw zawiera metody do rysowania tekstu, ustawiania czcionki i ustawiania atramentu w pisaku. W tym kodzie java. awt. Font i java. awt. Color są abstrakcjami, które są zaimplementowane z nietypowymi typami, o których dowiesz się w rozdziale 3.1. Do tego czasu szczegóły zostawiamy StdDraw. Domyślnym kolorem tuszu jest czarny, a domyślną czcionką jest 16-punktowa zwykła czcionka Serif. Podwójne buforowanie. StdDraw obsługuje potężną funkcję grafiki komputerowej zwaną podwójnym buforowaniem. Gdy podwójne buforowanie jest włączone przez wywołanie enableDoubleBuffering (). cały rysunek odbywa się na płótnie na ekranie. Płaszczyzna poza ekranem nie jest wyświetlana, istnieje tylko w pamięci komputera. Tylko wtedy, gdy wywołasz show (), twój rysunek zostanie skopiowany z płótna na ekranie do płótna na ekranie. gdzie jest wyświetlany w standardowym oknie rysunku. Możesz myśleć o podwójnym buforowaniu jako o zbieraniu wszystkich linii, punktów, kształtów i tekstu, które każesz mu narysować, a następnie losowaniu wszystkich jednocześnie, na żądanie. Jednym z powodów używania podwójnego buforowania jest wydajność przy wykonywaniu dużej liczby poleceń rysowania. Animacje komputerowe. Naszym najważniejszym zastosowaniem podwójnego buforowania jest tworzenie animacji komputerowych. gdzie tworzymy iluzję ruchu poprzez szybkie wyświetlanie statycznych rysunków. Możemy tworzyć animacje powtarzając następujące cztery kroki: Wyczyść płótno poza ekranem. Rysuj obiekty poza ekranem Skopiuj płótno na zewnątrz do płótna ekranowego. Zaczekaj chwilę. Wspierając te kroki, StdDraw ma kilka metod: Program Hello, World dla animacji ma wytworzyć czarną kulę, która wydaje się poruszać na płótnie, odbijając się od granicy zgodnie z prawami kolizji sprężystej. Przypuśćmy, że piłka znajduje się na pozycji (x. Y) i chcemy stworzyć wrażenie przeniesienia jej do nowej pozycji, powiedzmy (x 0,01, y 0,02). Robimy to w czterech krokach: Wyczyść płótno na ekranie w kolorze białym. Narysuj czarną kulkę w nowej pozycji na płótnie na ekranie. Skopiuj płótno na zewnątrz do płótna na ekranie. Zaczekaj chwilę. Aby stworzyć iluzję ruchu, BouncingBall. java iteruje te kroki dla całej sekwencji pozycji piłki. Obrazy. Nasza standardowa biblioteka rysunków obsługuje rysowanie obrazów oraz kształtów geometrycznych. Polecenie StdDraw. picture (x, y, filename) wyświetla obraz w podanej nazwie (w formacie JPEG, GIF lub PNG) na kanwie, wyśrodkowany (x, y). BouncingBallDeluxe. java ilustruje przykład, w którym odbijająca się piłka jest zastępowana obrazem piłki tenisowej. Interakcja użytkownika. Nasza standardowa biblioteka rysunków zawiera również metody, dzięki którym użytkownik może wchodzić w interakcję z oknem za pomocą myszy. Pierwszy przykład. MouseFollower. java to interakcja z użytkownikiem HelloWorld. Wyciąga niebieską kulkę, skupioną na lokalizacji myszy. Gdy użytkownik przytrzyma przycisk myszy, piłka zmienia kolor z niebieskiego na błękitny. Prosty atraktor. OneSimpleAttractor. java symuluje ruch niebieskiej kuli przyciągniętej do myszy. Obejmuje również siłę oporu. Wiele prostych atraktorów. SimpleAttractors. java symuluje ruch 20 niebieskich kulek przyciągniętych do myszy. Obejmuje również siłę oporu. Kiedy użytkownik kliknie, kulki rozproszą się losowo. Springs. Springs. java wdraża system sprężyn. Standardowy dźwięk. StdAudio to biblioteka, której można używać do odtwarzania i manipulowania plikami dźwiękowymi. Pozwala na odtwarzanie, manipulowanie i syntezowanie dźwięku. Przedstawiamy kilka podstawowych pojęć związanych z jednym z najstarszych i najważniejszych obszarów informatyki i informatyki naukowej: przetwarzanie cyfrowego sygnału. Koncert A. Koncert A jest falą sinusoidalną, skalowaną do oscylacji z częstotliwością 440 razy na sekundę. Funkcja sin (t) powtarza się raz na każde 2pi jednostek na osi X, więc jeśli mierzymy t w sekundach i wykreślamy funkcję sin (2pi t razy 440) otrzymujemy krzywą, która oscyluje 440 razy na sekundę. Amplituda (wartość-y) odpowiada objętości. Zakładamy, że jest skalowany między minus 1 a 1. Inne uwagi. Prosta formuła matematyczna charakteryzuje inne nuty w skali chromatycznej. Są one równo podzielone w skali logarytmicznej (podstawowa 2): na skali chromatycznej jest dwanaście nut, a my otrzymujemy nutę powyżej danej nuty przez pomnożenie jej częstotliwości przez (i 12) moc 2. dwukrotnie lub o połowę częstotliwość, poruszasz się w górę lub w dół oktawy na skali. Na przykład 880 herców ma oktawę powyżej koncertu A, a 110 herców ma dwie oktawy poniżej koncertu A. Próbkowanie. W przypadku dźwięku cyfrowego reprezentujemy krzywą, pobierając ją w regularnych odstępach czasu, dokładnie tak samo, jak przy wykreślaniu wykresów funkcji. Próbujemy wystarczająco często, że mamy dokładną reprezentację krzywej szeroko stosowana częstotliwość próbkowania jest 44 100 próbek na sekundę. To takie proste: reprezentujemy dźwięk jako tablicę liczb (liczby rzeczywiste, które są między minus 1 i 1). Na przykład poniższy fragment kodu odtwarza koncert A przez 10 sekund. Zagraj w tę melodię. PlayThatTune. java to przykład pokazujący, jak łatwo możemy tworzyć muzykę za pomocą StdAudio. Wykonuje notatki ze standardowego wejścia, indeksowane w skali chromatycznej z koncertu A i odtwarza je na standardowym dźwięku. Napisz program MaxMin. java, który odczytuje liczby całkowite (tyle, ile użytkownik wprowadza) ze standardowego wejścia i wypisuje wartości maksymalne i minimalne. Napisz program Stats. java, który pobiera argument n linii poleceń. odczytuje n liczb zmiennoprzecinkowych ze standardowego wejścia i wypisuje ich średnią (wartość średnią) i standardowe odchylenie próbki (pierwiastek kwadratowy z sumy kwadratów ich różnic od średniej, podzielony przez n minus 1). Napisz program LongestRun. java, który odczytuje sekwencję liczb całkowitych i wypisuje zarówno liczbę całkowitą, która pojawia się w najdłuższym kolejnym przebiegu, jak i długość przebiegu. Na przykład, jeśli wejście to 1 2 2 1 5 1 1 7 7 7 7 1 1. następnie twój program powinien wydrukować Najdłuższy cykl: 4 kolejne 7s. Napisz program WordCount. java, który odczytuje tekst ze standardowego wejścia i wypisuje liczbę słów w tekście. Na potrzeby tego ćwiczenia słowo jest ciągiem znaków spoza białych znaków otoczonych białymi znakami. Napisz program Closest. java, który pobiera trzy argumenty wiersza poleceń (x, y, z), odczytuje ze standardowego wejścia sekwencję współrzędnych punktu ((xi, yi, zi)) i wypisuje współrzędne punktu najbliżej ((x, y, z)). Przypomnijmy, że kwadrat odległości między ((x, y, z)) i ((xi, yi, zi)) wynosi ((x - xi) 2 (y - yi) 2 (z - zi) 2). Aby uzyskać efektywność, nie używaj Math. sqrt () ani Math. pow (). Biorąc pod uwagę pozycje i masy sekwencji obiektów, napisz program, aby obliczyć ich środek masy lub środek ciężkości. Środek ciężkości jest średnią pozycją n obiektów, ważoną masą. Jeśli pozycje i masy są podane przez (xi. Yi mi), to centroid (x. Y. M) jest podany przez: Napisz program Centroid. java, który czyta w sekwencji pozycji i mas (xi yi. mi) ze standardowego wejścia i wypisuje ich środek masy (x. y. m). Wskazówka . modeluj swój program po Average. java. Napisz program Checkerboard. java, który pobiera argument n linii komend i rysuje szachownicę n-po-n z czerwonymi i czarnymi kwadratami. Pokoloruj lewy dolny kwadrat czerwony. Napisz program Rose. java, który przyjmuje argument linii poleceń n i rysuje różę z n płatkami (jeśli n jest nieparzyste) lub 2n płatkami (jeśli n jest liczbą parzystą) przez wykreślenie współrzędnych biegunowych (r, theta) funkcji r sin (n razy theta) dla theta w zakresie od 0 do 2pi radianów. Poniżej znajduje się pożądany wynik dla n4, 7 i 8. Napisz program Banner. java, który pobiera ciąg s z wiersza poleceń i wyświetla go w stylu banera na ekranie, przesuwając się od lewej do prawej i zawijając z powrotem na początek ciągu znaków po osiągnięciu końca. Dodaj drugi argument linii poleceń, aby kontrolować prędkość. Napisz program Circles. java, który rysuje wypełnione kółka o losowym rozmiarze w losowych pozycjach w kwadracie jednostki, tworząc obrazy takie jak te poniżej. Twój program powinien przyjąć cztery argumenty wiersza polecenia: liczbę okręgów, prawdopodobieństwo, że każde koło jest czarne, minimalny promień i maksymalny promień. Spirografy do ćwiczeń kreatywnych. Napisz program Spirograph. java, który pobiera trzy argumenty linii poleceń R, r, a i rysuje powstały spirograf. A spirograph (technically, an epicycloid) is a curve formed by rolling a circle of radius r around a larger fixed circle or radius R. If the pen offset from the center of the rolling circle is (ra), then the equation of the resulting curve at time t is given by Such curves were popularized by a best-selling toy that contains discs with gear teeth on the edges and small holes that you could put a pen in to trace spirographs. For a dramatic 3d effect, draw a circular image, e. g. earth. gif instead of a dot, and show it rotating over time. Heres a picture of the resulting spirograph when R 180, r 40, and a 15. Clock. Write a program Clock. java that displays an animation of the second, minute, and hour hands of an analog clock. Use the method StdDraw. show(1000) to update the display roughly once per second. Wskazówka . this may be one of the rare times when you want to use the operator with a double - it works the way you would expect. Oscilloscope. Write a program Oscilloscope. java to simulate the output of an oscilloscope and produce Lissajous patterns. These patterns are named after the French physicist, Jules A. Lissajous, who studied the patterns that arise when two mutually perpendicular periodic disturbances occur simultaneously. Assume that the inputs are sinusoidal, so tha the following parametric equations describe the curve: Take the six parameters A x . w x . theta x . theta y . w y . and theta y from the command line. For example, the first image below has Ax Ay 1, w x 2, w y 3, theta x 20 degrees, theta y 45 degrees. The other has parameters (1, 1, 5, 3, 30, 45) Web Exercises Word and line count. Modify WordCount. java so that reads in text from standard input and prints out the number of characters, words, and lines in the text. Rainfall problem. Write a program Rainfall. java that reads in nonnegative integers (representing rainfall) one at a time until 999999 is entered, and then prints out the average of value (not including 999999). Remove duplicates. Write a program Duplicates. java that reads in a sequence of integers and prints back out the integers, except that it removes repeated values if they appear consecutively. For example, if the input is 1 2 2 1 5 1 1 7 7 7 7 1 1, your program should print out 1 2 1 5 1 7 1. Run length encoding. Write a program RunLengthEncoder. java that encodes a binary input using run length encoding. Write a program RunLengthDecoder. java that decodes a run length encoded message. Head and tail. Write programs Head. java and Tail. java that take an integer command line input N and print out the first or last N lines of the given file. (Print the whole file if it consists of For example the message VENI, VIDI, VICI is converted to YHQL, YLGL, YLFL. Write a program Caesar. java that takes a command-line argument k and applies a Caesar cipher with shift k to a sequence of letters read from standard input. If a letter is not an uppercase letter, simply print it back out. Caesar cipher decoding. How would you decode a message encrypted using a Caesar cipher Hint . you should not need to write any more code. Parity check. A Boolean matrix has the parity property when each row and each column has an even sum. This is a simple type of error-correcting code because if one bit is corrupted in transmission (bit is flipped from 0 to 1 or from 1 to 0) it can be detected and repaired. Heres a 4 x 4 input file which has the parity property: Write a program ParityCheck. java that takes an integer N as a command line input and reads in an N-by-N Boolean matrix from standard input, and outputs if (i) the matrix has the parity property , or (ii) indicates which single corrupted bit (i, j) can be flipped to restore the parity property, or (iii) indicates that the matrix was corrupted (more than two bits would need to be changed to restore the parity property). Use as little internal storage as possible. Hint: you do not even have to store the matrix Takagis function. Plot Takagis function: everywhere continuous, nowhere differentiable. Hitchhiker problem. You are interviewing N candidates for the sole position of American Idol. Every minute you get to see a new candidate, and you have one minute to decide whether or not to declare that person the American Idol. You may not change your mind once you finish interviewing the candidate. Suppose that you can immediately rate each candidate with a single real number between 0 and 1, but of course, you dont know the rating of the candidates not yet seen. Devise a strategy and write a program AmericanIdol that has at least a 25 chance of picking the best candidate (assuming the candidates arrive in random order), reading the 500 data values from standard input. Solution: interview for N2 minutes and record the rating of the best candidate seen so far. In the next N2 minutes, pick the first candidate that has a higher rating than the recorded one. This yields at least a 25 chance since you will get the best candidate if the second best candidate arrives in the first N2 minutes, and the best candidate arrives in the final N2 minutes. This can be improved slightly to 1e 0.36788 by using essentially the same strategy, but switching over at time Ne. Nested diamonds. Write a program Diamonds. java that takes a command line input N and plots N nested squares and diamonds. Below is the desired output for N 3, 4, and 5. Regular polygons. Create a function to plot an N-gon, centered on (x, y) of size length s. Use the function to draws nested polygons like the picture below. Bulging squares. Write a program BulgingSquares. java that draws the following optical illusion from Akiyoshi Kitaoka The center appears to bulge outwards even though all squares are the same size. Spiraling mice. Suppose that N mice that start on the vertices of a regular polygon with N sides, and they each head toward the nearest other mouse (in counterclockwise direction) until they all meet. Write a program to draw the logarithmic spiral paths that they trace out by drawing nested N-gons, rotated and shrunk as in this animation. Spiral. Write a program to draw a spiral like the one below. Globe. Write a program Globe. java that takes a real command-line argument alpha and plots a globe-like pattern with parameter alpha. Plot the polar coordinates (r, theta) of the function f(theta) cos(alpha times theta) for theta ranging from 0 to 7200 degrees. Below is the desired output for alpha 0.8, 0.9, and 0.95. Drawing strings. Write a program RandomText. java that takes a string s and an integer N as command line inputs, and writes the string N times at a random location, and in a random color. 2D random walk. Write a program RandomWalk. java to simulate a 2D random walk and animate the results. Start at the center of a 2N-by-2N grid. The current location is displayed in blue the trail in white. Rotating table. You are seated at a rotating square table (like a lazy Susan), and there are four coins placed in the four corners of the table. Your goal is to flip the coins so that they are either all heads or all tails, at which point a bell rings to notify you that you are done. You may select any two of them, determine their orientation, and (optionally) flip either or both of them over. To make things challenging, you are blindfolded, and the table is spun after each time you select two coins. Write a program RotatingTable. java that initializes the coins to random orientations. Then, it prompts the user to select two positions (1-4), and identifies the orientation of each coin. Next, the user can specify which, if any of the two coins to flip. The process repeats until the user solves the puzzle. Rotating table solver. Write another program RotatingTableSolver. java to solve the rotating table puzzle. One effective strategy is to choose two coins at random and flip them to heads. However, if you get really unlucky, this could take an arbitrary number of steps. Goal: devise a strategy that always solves the puzzle in at most 5 steps. Hex. Hex is a two-player board game popularized by John Nash while a graduate student at Princeton University, and later commercialized by Parker Brothers. It is played on a hexagonal grid in the shape of an 11-by-11 diamond. Write a program Hex. java that draws the board. Projectile motion with drag. Write a program BallisticMotion. java that plots the trajectory of a ball that is shot with velocity v at an angle theta. Account for gravitational and drag forces. Assume that the drag force is proportional to the square of the velocity. Using Newtons equations of motions and the Euler-Cromer method, update the position, velocity, and acceleration according to the following equations: Use G 9.8, C 0.002, and set the initial velocity to 180 and the angle to 60 degrees. Heart. Write a program Heart. java to draw a pink heart: Draw a diamond, then draw two circles to the upper left and upper right sides. Changing square. Write a program that draws a square and changes its color each second. Simple harmonic motion. Repeat the previous exercise, but animate the Lissajous patterns as in this applet. Ex: A B w x w y 1, but at each time t draw 100 (or so) points with phi x ranging from 0 to 720 degrees, and phi x ranging from 0 to 1080 degrees. Bresenhams line drawing algorithm. To plot a line segment from (x1, y1) to (x2, y2) on a monitor, say 1024-by-1024, you need to make a discrete approximation to the continuous line and determine exactly which pixels to turn on. Bresenhams line drawing algorithm is a clever solution that works when the slope is between 0 and 1 and x1 Modify Bresenhams algorithm to handle arbitrary line segments. Millers madness. Write a program Madness. java to plot the parametric equation: where the parameter t is in radians. You should get the following complex picture. Experiment by changing the parameters and produce original pictures. Fays butterfly. Write a program Butterfly. java to plot the polar equation: where the parameter t is in radians. You should get an image like the following butterfly-like figure. Experiment by changing the parameters and produce original pictures. Student database. The file students. txt contains a list of students enrolled in an introductory computer science class at Princeton. The first line contains an integer N that specifies the number of students in the database. Each of the next N lines consists of four pieces of information, separated by whitespace: first name, last name, email address, and section number. The program Students. java reads in the integer N and then N lines of data of standard input, stores the data in four parallel arrays (an integer array for the section number and string arrays for the other fields). Then, the program prints out a list of students in section 4 and 5. Shuffling. In the October 7, 2003 California state runoff election for governor, there were 135 official candidates. To avoid the natural prejudice against candidates whose names appear at the end of the alphabet (Jon W. Zellhoefer), California election officials sought to order the candidates in random order. Write a program program Shuffle. java that takes a command-line argument N, reads in N strings from standard input, and prints them back out in shuffled order. (California decided to randomize the alphabet instead of shuffling the candidates. Using this strategy, not all N possible outcomes are equally likely or even possible For example, two candidates with very similar last names will always end up next to each other.) Reverse. Write a program Reverse. java that reads in an arbitrary number of real values from standard input and prints them in reverse order. Time series analysis. This problem investigates two methods for forecasting in time series analysis. Moving average or exponential smoothing. Polar plots. Create any of these polar plots. Java games. Use StdDraw. java to implement one of the games at javaunlimited. Consider the following program. Suppose the file input. txt contains the following integers: What is the contents of the array a after running the following command High-low. Shuffle a deck of cards, and deal one to the player. Prompt the player to guess whether the next card is higher or lower than the current card. Repeat until player guesses it wrong. Game show. used this. Elastic collisions. Write a program CollidingBalls. java that takes a command-line argument n and plots the trajectories of n bouncing balls that bounce of the walls and each other according to the laws of elastic collisions. Assume all the balls have the same mass. Elastic collisions with obstacles. Each ball should have its own mass. Put a large ball in the center with zero initial velocity. Brownian motion. Statistical outliers. Modify Average. java to print out all the values that are larger than 1.5 standard deviations from the mean. You will need an array to store the values. Optical illusions. Create a Kofka ring or one of the other optical illusions collected by Edward Adelson. Computer animation. In 1995 James Gosling presented a demonstration of Java to Sun executives, illustrating its potential to deliver dynamic and interactive Web content. At the time, web pages were fixed and non-interactive. To demonstrate what the Web could be, Gosling presented applets to rotate 3D molecules, visualize sorting routines, and Duke cart-wheeling across the screen. Java was officially introduced in May 1995 and widely adopted in the technology sector. The Internet would never be the same. Program Duke. java reads in the 17 images T1.gif through T17.gif and produces the animation. To execute on your computer, download the 17 GIF files and put in the same directory as Duke. java . (Alternatively, download and unzip the file duke. zip or duke. jar to extract all 17 GIFs.) Cart-wheeling Duke. Modify Duke. java so that it cartwheels 5 times across the screen, from right to left, wrapping around when it hits the window boundary. Repeat this cart-wheeling cycle 100 times. Wskazówka . after displaying a sequence of 17 frames, move 57 pixels to the left and repeat. Name your program MoreDuke. java. Tac (cat backwards). Write a program Tac. java that reads lines of text from standard input and prints the lines out in reverse order. Game. Implement the game dodge using StdDraw . move a blue disc within the unit square to touch a randomly placed green disc, while avoiding the moving red discs. After each touch, add a new moving red disc. Simple harmonic motion. Create an animation like the one below from Wikipedia of simple harmonic motion. Yin yang. Draw a yin yang using StdDraw. arc() . Twenty questions. Write a program QuestionsTwenty. java that plays 20 questions from the opposite point of view: the user thinks of a number between 1 and a million and the computer makes the guesses. Use binary search to ensure that the computer needs at most 20 guesses. Write a program DeleteX. java that reads in text from standard input and deletes all occurrences of the letter X. To filter a file and remove all Xs, run your program with the following command: Write a program ThreeLargest. java that reads integers from standard input and prints out the three largest inputs. Write a program Pnorm. java that takes a command-line argument p, reads in real numbers from standard input, and prints out their p-norm . The p-norm norm of a vector (x 1 . x N ) is defined to be the pth root of (x 1 p x 2 p . x N p ). Consider the following Java program. Suppose that the file input. txt contains the integers 1 and 1. What does the following command do Modify Add. java so that it re-asks the user to enter two positive integers if the user types in a non-positive integer. Modify TwentyQuestions. java so that it re-asks the user to enter a response if the user types in something other than true or false . Hint: add a do-while loop within the main loop. Nonagram. Write a program to plot a nonagram. Star polygons. Write a program StarPolygon. java that takes two command line inputs p and q, and plots the - star polygon. Complete graph. Write a program to plot that takes an integer N, plots an N-gon, where each vertex lies on a circle of radius 256. Then draw a gray line connecting each pair of vertices. Necker cube. Write a program NeckerCube. java to plot a Necker cube. What happens if you move the StdDraw. clear(Color. BLACK) command to before the beginning of the while loop in BouncingBall. java. Odpowiedź . try it and observe a nice woven 3d pattern with the given starting velocity and position. What happens if you change the parameter of StdDraw. show() to 0 or 1000 in BouncingBall. java. Write a program to plot a circular ring of width 10 like the one below using two calls to StdDraw. filledCircle() . Write a program to plot a circular ring of width 10 like the one below using a nested for loop and many calls to StdDraw. point() . Write a program to plot the Olympic rings. Write a program BouncingBallDeluxe. java that embellishes BouncingBall. java by playing a sound effect upon collision with the wall using StdAudio and the sound file pipebang. wav. Last modified on February 20, 2017. Copyright copy 2000ndash2018 Robert Sedgewick and Kevin Wayne. Wszelkie prawa zastrzeżone.
Comments
Post a Comment