Skip to content

Implemented solution and explanation for ReverseInts #154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions problem-set/ReverseInts.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* File: ReverseInts.java
* ----------------------------
* ReverseInts-ის საშუალებით მომხმარებლის მიერ შემოყვანილ რიცხვებს დავბეჭდავთ შებრუნებული მიმდევრობით.
*
* ამოცანის პირობა:
* კონსოლიდან შეგვყავს რიცხვები მანამ სანამ არ შეიყვანთ -1-ს, დაბეჭდეთ შეყვანილი რიცხვები შებრუნებული მიმდევრობით.
*
* დამატებითი ახსნის სანახავად იხილეთ /problem-set/ReverseInts.md
*/
import java.util.*;

import acm.program.*;

public class BlankClass extends ConsoleProgram {
private static final int SENTINEL = -1;
public void run() {
println("This program reverses the elements in an ArrayList.");
println("Use " + SENTINEL + " to signal the end of the list.");
ArrayList<Integer> list = readArrayList();
reversePrintArrayList(list);
}
/*
* This method reads user input and saves all
* values in an Integer ArrayList. After SENTINEL
* is entered, ArrayList is returned.
*/
private ArrayList<Integer> readArrayList() {
ArrayList<Integer> list = new ArrayList<Integer>();
while(true) {
int n = readInt("Enter a number: ");
if(n == SENTINEL) break;
list.add(n);
}
return list;
}
/*
* This method takes an Integer ArrayList and
* prints it's elements one by one in reverse.
*/
private void reversePrintArrayList(ArrayList<Integer> list) {
int length = list.size();
for(int i=length-1;i>=0;i--) {
println(list.get(i));
}
}
}
60 changes: 60 additions & 0 deletions problem-set/ReverseInts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# ReverseInts

ამოცანა:
```
კონსოლიდან შეგვყავს რიცხვები მანამ სანამ არ შეიყვანთ -1-ს, დაბეჭდეთ შეყვანილი
რიცხვები შებრუნებული მიმდევრობით.
```
## ამოცანის ამოხსნა
ამოცანა დავყოთ ორ კომპონენტად:
* მომხმარებლის ინფუთის წაკითხვა და შენახვა.
* რიცხვების შებრუნებული მიმდევრობით დაბეჭდვა.
ორივე კომპონენტისთვის ცალკე მეთოდი დავწეროთ.

### ინფუთის წაკითხვა და შენახვა
ინფუთის წასაკითხად გამოვიყენოთ ბრძანება `readInt()`. მომხმარებლისთვის ადვილად გასაგები რომ იყოს, `readInt()` ბრძანებას არგუმენტად გადავცეთ რაიმე სტრინგი. შემოსული რიცხვი კი ცვლადში შევინახოთ. ამოხსნის ეს ნაწილი კოდში შემდეგნაირად აისახება:
```java
int n = readInt("Enter a number: ");
```
ამოცანის პირობის თანახმად, რიცხვები შეგვყავს მანამ, სანამ -1-ს არ შევიყვანთ. ე.ი. წინასწარ არ ვიცით რამდენი რიცხვი შემოდის. ასეთ შემთხვევაში გვჭირდება `while()` ციკლი. ყოველ იტერაციაზე წავიკითხავთ მომხმარებლის შემოყვანილ რიცხვს და შევანმოწმებთ -1 ხომ არ შემოიყვანა, რის შემთხვევაშიც ციკლი უნდა დავასრულოთ. კოდში ეს ასე აისახება:
```java
while(true) {
int n = readInt("Enter a number: ");
if(n == SENTINEL) break;
}
```
ინფუთის წაკითხვის გარდა გვჭირდება მისი შენახვა. რადგანაც წინასწარ არ ვიცით რიცხვების რაოდენობა, შეგვიძლია `ArrayList` კლასი გამოვიყენოთ. ამისათვის დაგვჭირდება `java.util.*`-ის დაომპორტება:
```java
import java.util.*;
```
შევქმნათ `ArrayList<Integer> list` და ყოველი შემოსული რიცხვი შევინახოთ მასში (გარდა -1-ისა). როდესაც დავასრულებთ რიცხვების წაკითხვას, `list` დავაბრუნოთ.
ეს ყველაფერი ერთი მეთოდის ნაწილი იქნება, რომელსაც კითხვადობისათვის დავარქვათ `readArrayList()`. მთლიანობაში კოდს ასეთი სახე ექნება:
```java
private ArrayList<Integer> readArrayList() {
ArrayList<Integer> list = new ArrayList<Integer>();
while(true) {
int n = readInt("Enter a number: ");
if(n == SENTINEL) break;
list.add(n);
}
return list;
}
```
### რიცხვების შებრუნებული მიმდევრობით დაბეჭდვა
შემოყვანილი რიცხვები `list`-ში გვაქვს დამახსოვრებული და ახლა მათი შებრუნებული თანმიმდევრობით დაბეჭდვა გვინდა. ეს `for()` ციკლით გავაკეთოთ. თუკი `list`-ს ბოლოდან გადავუყვებით და ყოველ ელემენტს დავბეჭდავთ, რიცხვები შებრუნებული მიმდევრობით დაიბეჭდება. ამისათვის შევინახოთ `list`-ის ზომა რაიმე ცვლადში და `for()` ციკლს შემდეგი სახე მივცეთ:
```java
int length = list.size();
for(int i=length-1;i>=0;i--) {
println(list.get(i));
}
```
ამისთვისაც ცალკე მეთოდი გავაკეთოთ, რომელსაც არგუმენტად `list`-ს გადავცემთ.

## რატომ იმუშავებს ამოხსნა ნებისმიერი შემოყვანილი მონაცემებისთვის?
რადგანაც მონაცემების წაკითხვა `while()` ციკლით გვიწერია, ამოხსნა იმუშავებს ნებისმიერი რაოდენობის ინფუთისთვის. `while()` ციკლი წაიკითხავს და შეინახავს რიცხვებს მანამ, სანამ მომხმარებელი -1-ს არ შემოიყვანს.

## რატომ გამოვიყენეთ `ArrayList` და არა `Array`?
`Array`-ს შესაქმნელად აუცილებელია წინასწარ ვიცოდეთ მისი ზომა. `ArrayList`-ს კი ეს საჭიროება არ გააჩნია, რაც ძალიან გვეხმარება ამ ამოცანის ამოხსნაში. რადგანაც წინასწარ არ ვიცით რამდენ რიცხვს შემოიყვანს მომხმარებელი, ამიტომაც არის სასარგებლო `ArrayList`-ით დაწერა. `Array`-ს საშუალებითაც შეგვეძლო ამოხსნა, თუკი წინასწარ განსაზღვრული ზომის გაცდენის შემთხვევაში ახალ `Array`-ს შევქმნიდით და ძველის მნიშვნელობებს გადავაკოპირებდით, თუმცა `ArrayList`-ით ბევრად მარტივი და მოსახერხებელია.

## რატომ არის -1 კონსტანტა?
-1 გატანილია როგორც მუდმივი მნიშვნელობა და აღნიშნულია `SENTINEL`-ით. ამ მიდგომას ის უპირატესობა აქვს, რომ -1-ის მაგივრად სხვა რიცხვის გამოყენება რომ გვინდოდეს წაკითხვის შესაჩერებლად, კოდს ადვილად შევცვლიდით. კონსტანტა კი იმიტომ არის, რომ მისი ცვლილება არ ხდებოდეს პროგრამის მიმდინარეობისას.