Skip to content

Print thyself 52 #150

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 2 commits 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
32 changes: 32 additions & 0 deletions problem-set/PrintThyself.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# PrintThyself

პრობლემა:
```
დაწერეთ პროგრამა, რომელიც წაიკითხავს თAვის თავს ფაილიდან და დაბეჭდავს კონსოლში
```




## პრობლემის გადაჭრის გზა
საკითხი ძალიან მარტივია, უპირველეს ყოვლისა უნდა ვცადოთ ფაილის გახსნა, შემდეგ კი წავიკითხოთ და შევინახოთ თითოეული ხაზი

### როგორ გავხსნათ ფაილი?
ფაილის წასაკითხად საკმარისია გამოვიყენოთ `BufferedReader` და `FileReader` მეთოდები, რომლებიც `java.io` ბიბლიოთეკის ნაწილია. თუმცა მხოლოდ ეს როდია საკმარისი, თუ ფაილის სახელს არასწორად შევიყვანთ ან თუნდაც არარსებულ ფაილს მივუთითებთ მივიღებთ ბაგებს. თუმცა ამის ასარიდებლად შეგვიძლია გამოვიყენოთ `try { .. } catch { .. }`, შედეგად მივიღებთ შემდეგ კოდს

```java
try{

BufferedReader br = new BufferedReader(new FileReader(fileName));
//To-Do ...

}catch(Exception e){
//Error Message
}
```

### როგორ წავიკითხოთ ფაილიდან?
ეს ნაწილი საკმაოდ მარტივია, ფაილიდან ხაზის წაკითხვა შეგვიძლია `BufferedReader-ის` `readLine()` მეთოდის გამოყენებით, შესაბამისად შეგვიძლია ეს ფუნქცია მოვათავსოთ `While(true)` ციკლში, მაგრამ როდის უნდა გავაჩეროთ ციკლი? ესეც ძალიან მარტივია, მაშინ როდესაც `readLine()-ს` ფაილის დასასრულში ვიძახებთ ის აბრუნებს `null-ს`, ამიტომ შეგვიძლია ყოველ `readLine()-ს` გამოძახებას თან დავურთოთ შესაბამისი შემოწმებაც `if(readLine() == null) break;`.

## შესაძლო ხარვეზები
ერთადერთი ხარვეზი რომელიც ზემოთ არ გაგვითვალიწნიებია გახლავთ - ფაილის დახურვა. მართალია ამ შემთხვევაში მოცემულ ამოცანას მაინც შეასრულებს ჩვენი კოდი, მაგრამ სხვა დროს, იმ შემთხვევაში თუ ფაილს არ დავხურავთ, შემდეგ კი მის ხელახლა გამოყენებას ვცდით მივიღებთ უამრავ შეცდომას და ვერც კი მივხვდებით რისი ბრალი შეიძლება იყოს. ამიტომ `while` ციკლის დასასრულს უბრალოდ შეგვიძლია დავწეროთ `br.close()` რომელიც დახურავს ჩვენს მიერ გახსნილ ფაილს
61 changes: 61 additions & 0 deletions problem-set/PrintThyself.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* File: PrintThyself.java
* ---------------------------------
* დაწერეთ პროგრამა რომელიც წაიკითხავს თავის თავს
* ფაილიდან და დაბეჭდავს კონსოლში
*/

import java.io.BufferedReader;
import java.io.FileReader;

import acm.graphics.GOval;
import acm.program.*;

public class ConsoleProgrammSample extends ConsoleProgram {

private static final String FILE_NOT_FOUND_MESSAGE = "- ERROR - Can't Locate Recevied File - ERROR -";

private String readFile(String fileName) {

//Trying To Open File
try {

String result = "";
BufferedReader br = new BufferedReader(new FileReader(fileName));

while(true) {

//Reading Every Line Of File
String newLine = br.readLine();
//If newLine == null, It Means That There Are No More Line To Read, So While Loop Breaks
if(newLine == null) break;

//Add newLine To "result"
result += newLine + '\n';
}

br.close();
//Return Result
return result;

}catch(Exception e) {

System.out.print(e);
}

//Return Error Message, If Code Catches Errors
return FILE_NOT_FOUND_MESSAGE;
}

public void run(){

//Read File Content
String fileName = readLine("Enter FileName: ");
String result = readFile(fileName);

//Print File Content
println("Received File Contains Text: ");
println(result);

}

}
Binary file added problem-set/images/ASCII_codes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added problem-set/images/Recursive_stringToInteger.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added problem-set/images/stringToInteger_function.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions problem-set/stringToInteger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* File: StringToInteger.java
* ---------------------------------
* დაწერეთ stringToInteger მეთოდი, რომელსაც გადაეცემა სტრინგი და აბრუნებს მთელ რიცხვს.
* ჩათვალეთ, რომ გადაცემული სტრინგი მხოლოდ ციფრებისგან შედგება და არ იწყება 0-ით.
* მაგალითად “234” გადაცემის შემთხვევაში მეთოდმა უნდა დააბრუნოს 234. ასევე ჩათვალეთ,
* რომ დაბრუნებული მნიშვნელობა დადებითია და ეტევა int-ში.
*/

import acm.program.*;

public class ConsoleProgrammSample extends ConsoleProgram {

//Function bellow transforms received string into the Integer
private int stringToInteger(String num) {

int result = 0;

for(int i = 0; i < num.length(); i++) {
result *= 10;
result += (num.charAt(i) - '0');
}

return result;
}

public void run() {

//Getting input from user
String num = readLine("Enter number in string: ");

//Checking if received string is not empty
if(num.length() != 0) {
int result = stringToInteger(num);
println("Converted: " + result);

}else {
println("No valid string received.");
}
}
}

114 changes: 114 additions & 0 deletions problem-set/stringToInteger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# StringToInteger

პრობლემა:
```
დაწერეთ stringToInteger მეთოდი, რომელსაც გადაეცემა სტრინგი და აბრუნებს მთელ რიცხვს.
ჩათვალეთ, რომ გადაცემული სტრინგი მხოლოდ ციფრებისგან შედგება და არ იწყება 0-ით.
მაგალითად “234” გადაცემის შემთხვევაში მეთოდმა უნდა დააბრუნოს 234. ასევე ჩათვალეთ,
რომ დაბრუნებული მნიშვნელობა დადებითია და ეტევა int-ში.
```




## პრობლემის გადაჭრის გზა
ვინაიდან შემოსული სტრინგები ყოველთვის ვალიდურია, ამოცანა შეგვიძლია დავყოთ 2 ნაწილად.
1. წავიკითხოთ String
2. შევქმნათ მეთოდი, რომელსაც არგუმენტად გადაეცემა სტრინგი და უკან დაგვიბრუნებს შესაბამის Integer-ს.


---

### პირველი ნაბიჯი
უპირველეს ყოვლისა, უნდა წავიკითხოთ String-ი, ამისთვის გამოვიყენოთ მეთოდი `readLine(...)`, რომელსაც არგუმენტად შეგვიძლია გადავცეთ გამოსატანი ტექსტი, მაგალითად
`readLine("შეიყვანეთ რიცხვი: )` დაბეჭდავს ტექსტ "შეიყვანეთ რიცხვი: " და დაელოდება მომხმარებლის Input-ს.

### მეორე ნაბიჯი
String-ის Integer-ად გარდასაქმნელად შევქმნათ ახალი მეთოდი `stringToInteger()`, რა თქმა უნდა, მოცემული მეთოდისთვის მოგვიწევს შემოსული String-ის გადაცემა,ამას გარდა მოგვიწევს გარდაქმნილი Integer-ის დაბრუნება, აქიდან გამომდინარე ჩვენი მეთოდი მიიღებს სახეს `private int stringToInteger(String num)`.

![StringToInteger Function](/problem-set/images/stringToInteger_function.png)

ახლა უკვე შეგვიძლია ჩვენს მთავარ პრობლემას მივხედოთ, ამოსახსნელი ალგორითმი არც თუ ისე რთულია, მარტივად გასაგებად განვიხილოთ 3 სიმბოლოიანი String, მაგალითად 321, ამასთანავე ჩავთვალოთ რომ ერთი სიმბოლოს Integer-ად გადაქცევა ვიცით (თუ როგორ მოგვიანებით ვიტყვით). ავიღოთ პირველი სიმბოლო ანუ 3 და შევინახოთ, მეორე სიმბოლოზე გადასვლისას კი შენახული რიცხვი ანუ 3 გავამრავლოთ 10-ზე და მას დავუმატოთ 2, ანალოგიურად მოვიქცეთ მესამე სიმბოლოზე გადასვლისასაც, ანუ შენახული 32 გავამრავლოთ 10-ზე და დავუმატოთ 1, თუ დავფიქრდებით რამდენჯერაც არ უნდა მოვიქცეთ მსგავსად ყოველთვის თავდაპირველ რიცხვს მივიღებთ.

![StringToInteger Function Algorithm](/problem-set/images/stringToInteger_function_algorithm.png)

ვინაიდან ალგორითმი უკვე განვიხილით შეგვიძლია კოდის წერასაც შევუდგეთ, განხილულის შემდეგ ალბათ ნათელია, რომ დაგვჭირდება `result` ცვლადი შესანახი მნიშვნელობებისთვის, ამასთანავე დაგვჭირდება თითოეული სიმბოლო String-დან, ამისთვის კი გამოვიყენეოთ `for` ციკლი, `string.length()` მეთოდი რომელიც შესაბამისი String-ის ზომას აბრუნებს და `string.charAt(index)` მეთოდი, რომელიც შესაბამისი სტრინგისთვი აბრუნებს გადაცემულ ინდექსზე მყოფ სიმბოლოს, მაგალითად შემდეგი კოდი დაგვიბეჭდავს `t სიმბოლოს`.

```java
String test = "StringToInteger";
println(test.charAt(1));
```

დასასრულს გვრჩება ერთი დეტალი, როგორ ვაქციოთ სიმბოლო Integer-ად? ეს ძალიან მარტივია ვინაიდან თითოეულ სიმბოლოს აქვს თავისი ASCII მნიშვნელობა (იხ.სურათი), თუ ეს სიტყვა არაფერს გეუბნებათ ნუ ინერვიულებთ უბრალოდ ჩათვალეთ, რომ თითოეულ სიმბოლოს რაღაც განსაზღვურლი რიცხვი შეესაბამება, ამასთან ერთად კი ვიცითი რომ თუ სიმბოლო 0-ს შეესაბამება რაღაც x რიცხვი 1-ს აუცილებლად შეესაბამება მასზე 1 ით მეტი, 2-ს ორით მეტი და ა.შ, აქიდან გამომდინარე თუ ყოველ სიმბოლოს გამოვაკლებთ 0-ის ASCII კოდის მნიშვნელობას მივიღებთ სწორედ ამ სიმბოლოს Integer სახით.

![ASCII Codes](/problem-set/images/ASCII_codes.png)

ამ ყველაფრის გათვალისწინებით მივიღებთ შემდეგ კოდს:

```java
int result = 0;

for(int i = 0; i < num.length(); i++) {
result *= 10;
result += (num.charAt(i) - '0');
}
```

აქ ნუ შეგაშინებთ ის მომენტი, რომ ჩვენ არა ASCII მნიშვნელობებს არამედ პირდაპირ სიმბოლოებს ვაკლებთ ერთმანეთს, ამ დროს კომპილატორმა იცის რომ ერთმანეთს სიმბოლოები კი არა არამედ მათი მნიშვნელობები უნდა გამოაკლოს ერთმანეთს.

---

## შესაძლო ხარვეზები
* შეცდომა, რომელიც კოდის რეალიზაციისას შეიძლება დავუშვათ გახლავთ result ცვლადის შექმნა ინიციალიზაციის გარეშე,
ასეთ დროს არ ვიცით რა მნიშვნელობას იღებს result ცვლადისთვის განკუთვნილი კონტეინერი მეხსიერებაში, შესაბამისად შესაძლოა
საბოლოოდ სრულიად სხვა პასუხი მივიღოთ, ჩვენს შემთხვევაში კომპილატორი კოდის გაშვების შესაძლებლობასაც არ გვაძლევს.

![Initialization Error StringToInteger](/problem-set/images/Initialization_error_stringToInteger.png)

* მიუხედავად იმისა რომ ყოველი შემოსული რიცხვი დადებითია და ამასთან ერთად ეტევა Int-ის საზღვრებში, არ უნდა გამოგვრჩეს შემთხვევა როდესაც მომხმარებელს შემოყავს ცარიელი სტრინგი. ამ პრობლემის მოსაგვარებლად უბრალოდ მოგვიწვეს კოდიში ერთი `If-ის` ჩამატება.

```java
if(string.length() != 0){
//TO-DO...
}else{
println("No input");
}
```

---

## სხვა ამოხსნები
მოცემული ამოცანის ამოხსნა სხვა გზებითაც შეგვიძლია, მაგალითად რეკურსიის გამოყენებით, თუ ეს სიტყვა არაფერს გეუბნებათ ეს პრობლემას სულაც არ წარმოადგენს, ვინაიდან ამ ეტაპზე ამის ცოდნა სულაც არ მოგეთხოვებათ, თუმცა ვისაც გაგიგიათ, შეგიძლიათ იხილოთ სურათი სადაც იგივე მეთოდია აღწერილი ყველანაირი ციკლენიბ გარეშე.

![Recursive StringToInteger](/problem-set/images/Recursive_stringToInteger.png)