// Code that shows Data Structures, Data, Inheritance, Usage of Interfaces, and Overriding of Object toString

// Define a class called Course with name, instructor, and level properties
class Course {
    constructor(name, instructor, level) {
      this.name = name;
      this.instructor = instructor;
      this.level = level;
    }
  
    // Override the toString method to return a string representation of the Course object
    toString() {
      return `Course[name=${this.name}, instructor=${this.instructor}, level=${this.level}]`;
    }
  }
  
  // Define an interface called Lesson with a method called learn
  class Lesson {
    learn() {
      throw new Error('Method learn() must be implemented');
    }
  }
  
  // Define a class called CodingLesson that inherits from Lesson and has language and editor properties
  class CodingLesson extends Lesson {
    constructor(language, editor) {
      super();
      this.language = language;
      this.editor = editor;
    }
  
    // Implement the learn method for the CodingLesson class
    learn() {
      console.log(`Learning ${this.language} programming using ${this.editor} editor`);
    }
  
    // Override the toString method to return a string representation of the CodingLesson object
    toString() {
      return `CodingLesson[language=${this.language}, editor=${this.editor}]`;
    }
  }
  
  // Define a data structure that uses the Course and CodingLesson classes
  const webDevelopmentCourse = new Course('Web Development', 'John Doe', 'Intermediate');
  const htmlLesson = new CodingLesson('HTML', 'VS Code');
  const cssLesson = new CodingLesson('CSS', 'Atom');
  const jsLesson = new CodingLesson('JavaScript', 'Sublime Text');
  
  const lessons = [htmlLesson, cssLesson, jsLesson];
  
  console.log(`Welcome to ${webDevelopmentCourse.name} course taught by ${webDevelopmentCourse.instructor} at ${webDevelopmentCourse.level} level`);
  
  lessons.forEach((lesson) => {
    console.log(`Lesson: ${lesson}`);
    lesson.learn();
  });
Queue<String> queue = new LinkedList<>();  // Queue interface uses LL implementation
queue.add("John");
queue.add("Jane");
queue.add("Bob");
// Collections has a toArray convertion
Object[] arr = queue.toArray();

// Empty queue
System.out.println("Empty Queue");
while (queue.size() > 0) // Interate while size
    System.out.println(queue.remove());

// Iterate of array
System.out.println("Iterate over Array");
for (Object a : arr) // Type is Object from convertion
    System.out.println(a);
Empty Queue
John
Jane
Bob
Iterate over Array
John
Jane
Bob

Classes and Objects CB

Class have the following Contructors: define the variables in the class. Accessors: are getters. They can access a contructor of a class. Mutator methods: are setters. they can set values for a contructor of a class.

Follow the format: object.method() These methods can be void methods or methods that return something. If the method takes a parameter, put the parameter in method

Static Methods These methods are inside a class, and you do not need to create objects of the class to use the methods. You can simply access the method through the class. Math Class in an example you can just say System.out.print(Math.sqrt(16)). you dont have to create a math object

String Class

You can create string objects by just assigning string literals String word = "theater"; Usually we don't have static methods for the String class.

We can pass an integer as a double, but we can't pass a double to an integer.

Combined Table Class

public class Book{
    private String title;
    private String genre;
    private int pages;
}
public class CombinedTable {
    SingleTable st1 = new SingleTable();
    SingleTable st2 = new SingleTable();
    int seatnum1 = st1.getNumSeats();
    int seatnum2 = st2.getNumSeats();

    int height1 = st1.getHeight();
    int height2 = st2.getHeight();

    double quality1 = st1.getViewQuality();
    double quality2 = st2.getViewQuality();

    public boolean combinedNumSeats(n){
        if ((num1 + num2 - 2)>=n){
            return true;
        }

        return false;
    }

    public double desireabilty(){
        double desireability = 0;
        if (height1 == height2){
            desireability = (quality1 + quality2)/2;
        }
        else{
            double temp = (quality1 + quality2)/2;
            desireability = temp - 10;
        }
        return desireability;

    }

}

2017 FRQ

// Question 1

public Digits (int num){
    int number = num;
    int count = 0;
    while (number>0){
        int remain = number%10;
        digitList.add(count, remain);
        number = number/10;
        count = count +1;
    }

}


public boolean isStrictlyIncreasing(){
    for (int i=0; i<digitList.size(); i++){
        if (digitList.get(i)>digitList.get(i+1)){
            return false;
        }

    }
    return true;
}
// Question 2

public class MultPractice implements StudyPractice{

    private int first;
    private int second;

    public MultPractice(int first, int second){
        first = first;
        second = second;
    }

    //if you add two integers before you introduce a string, then you will actually add the two numbers.
    // if you add two numbers after you introduce a string, the two numbers will only be next to each other. 
    public String getProblem(){
        String problem = first + " TIMES " + second
        return problem
    }

    public void nextProblem(){
        second = second + 1;
        // this.getProblem();  YOU DONT NEED THS LINE because in the example code, they are manually calling getProblem() again.    
    }
}
// Question 3

public void replaceNthOccurance(String str, int n, String repl){
    int index_n = this.findnthOccurance(str, n);
    if (index_n < str.length()){
        str = currentPrase.substring(0,index_n) + repl + currentPhrase.subtring(index_n);
    }
}

public int findLastOccurance(String str){
    String temp = currentPhrase;
    int first_index = temp.indexOf(str);
    int str_length = str.length();
    temp = currentPhrase.substring(first_index+str_length);
    if (temp.indexOf(str) == -1){
        return first_index
    }
    else{
        int count = 1
        while(temp.indexOf(str) != -1){
            int some_index = temp.indexOf(str);
            temp = temp.substring(some_index+str_length);
            count++;
        }
        int final_length = currentPrase.length - temp.length;
        return final_length - 1;
    }
}






//actual part b solution. they want you to use findNthOccurance()
public int findLastOccurrence(String str)
{
    int n = 1;
    int index = -1;
    int nextIndex = findNthOccurrence(str, n);
    while(nextIndex != -1)
        {
            index = nextIndex;
            n++;
            nextIndex = findNthOccurrence(str, n);
        }

    return index;
}

Linked Lists

Unlike arrays, you cannot directly go to the ellement that you want to. You have to start with the head - it takes linear time All the elements are linked.

You can add and delte elements from the beginning of the linked list, at constant time.

  • However, if you want to add and delete elements from the middle and end, you have to first go to that element, and then add it and delete.4

Doubly LInked Lists - Also linked from the back

public class Node{
    Node next;
    int data;
    public ListLists(int data){
        this.data = data;
    }

}
// Linked lists are all connected. So, you can do methods like current.next or head.next. 



public class LinkedList{
    Node head;

    /*
     * We have to go to the head, then keep going to the next, untill you add the elemtn you want.
     */
    public void append(int data){

        if (head == null){
            head = new Node(data);
            return
        }

        Node current = head;
        while(current.next !=null){
            current = current.next;
        }

        current.next = new Node(data);
    }

    /*
     * If we want to prepend to a linked list, then we have to set the old head to the head.next, and set the new head as head.
     */
    public void prepend(int data){
        Node newHead = new Node(data);
        newHead.next = head;
        head = newHead;

    }

     /*
     in linked lists, we do not actually delete any of the values. For example, if we want to "delete" the second element of the list
    we simply stop at the first, ignore the second element, and then go to the third. 

      */ 
    public void deteleteWithValue(int data){ 
        if (head==null){
            return
        }
        if(head.data == data){
            head = head.next;
            return;
        }

        Node current = head;
        while(current.next != null){
            if(current.next.data == data){
                current.next = current.next.next;
                return;
            }
            current = current.next;
        }
       
    }

}

Stacks and Queues

Both are linear data stuctures Flexible with sizes.

- can add and delete elements as you. 

Stack: LIFO - Last in, First out data structure. imagine a stack of plates, where the last one you put in, is the first to go.

Queue: FIFO - First in first out. imagine a line, or queue at a roller coaster. the first person in, the first person who is out.

Hacks

// 1
public class QueueExample {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<String>();

        // Adding elements to the queue
        queue.add("seven");
        System.out.println("Enqueued data: " + "seven");
        printQueue(queue);

        queue.add("slimy");
        System.out.println("Enqueued data: " + "slimy");
        printQueue(queue);

        queue.add("snakes");
        System.out.println("Enqueued data: " + "snakes");
        printQueue(queue);

        queue.add("sallying");
        System.out.println("Enqueued data: " + "sallying");
        printQueue(queue);

        queue.add("slowly");
        System.out.println("Enqueued data: " + "slowly");
        printQueue(queue);

        queue.add("slithered");
        System.out.println("Enqueued data: " + "slithered");
        printQueue(queue);

        queue.add("southward");
        System.out.println("Enqueued data: " + "southward");
        printQueue(queue);

        // Removing elements from the queue
        String data =queue.remove();

        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);
    }

    // Helper method to print the contents of the queue
    public static void printQueue(Queue<String> queue) {
        System.out.println("Words count: " + queue.size() + ", data: " + String.join(" ", queue));
        System.out.println();
    }
}

QueueExample.main(null);
// implementation of 1 and 5
public static class Queue{

    private static class Node{
        private int data;
        private Node next;
        private Node(int data){
            this.data = data;
        }
    }

    private Node head;
    private Node tail;
    
    public boolean isEmpty(){
        return head == true;
    }

    public int peek(){
        return head.data
    }

    public void add(int data){
        //add to the tail
        Node node = new Note(data);
        if (tail != null){
            tail.next = node;
        }
        tail = node;
        if (head ==null){
            head = node;
        }        
    }

    public int remove(){
        int data = head.data;
        head = head.next;
        if (head ==null){
            tail = null;
        }
        return data;
    }


}
//2 

public class Merge{
    public ListNode mergeTwoLists(listNode l1, listNode l2){
        ListNode temp_node = new ListNode(0);
        ListNode current_node = temp_node;
        while(l1!=null && l2 !== null){
            if (l1.val<l2.val){
                current_node.next = l1;
                l1 = l1.next
            }
            else{
                current_node.next = l2;
                l2 = l2.next;
            }

            current_node = current_node.next;
        }

        if((l1==null && l2!=null)){
            current_node.next = l2
            l2 = l2.next;
        }
        if((l1!=null && l2==null)){
            current_node.next = l1;
            l1 = l1.next;
        }

        return temp_node.next;
    }
}
//3 
public static class Queue{

    private static class Node{
        private int data;
        private Node next;
        private Node(int data){
            this.data = data;
        }
    }
    private Node current;
    
    while (node.current!= null){
        node.current = Math.random() *10;
    }
}
//4

/*
 * Since Queues are Lifos and Stacks are Fifos, if we take the first element from a queue, and add to a stack, the order of the elements in the original queue will be reveresed. 
 */

public class reverse{
    public static void main(String[] args){  
    Queue <Integer> queue = new ArrayDeque<>();
    queue.add(10);
    queue.add(20);
    queue.add(30);
    System.out.println(queue);

    Stack<Integer> stack = new Stack<>();
    while(!queue.isEmpty()){
        stack.push(queue.remove());
    }

    while(!stack.isEmpty()){
        queue.add(stack.pop());
    }
    System.out.print(queue);
}
}

reverse.main(null);
[10, 20, 30]
[30, 20, 10]

Enhanced For Loops or For Each loops

public class Enhanced{
    public static void main(String[] args){
        int[][] numbers = new int[10][20];
       int x = 0;
        for (int[] rows: numbers){
            for(int column: rows){
                column = column + x;
                x++;
                System.out.print(column +" ");
            }
            System.out.println();
        }
    }
}

Enhanced.main(null);
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 
public class GFG {
     
    // Main driver method
    public static void main(String[] args) {
         
        // Creating object of class1
        // inside main() method
        Complex c1 = new Complex(10, 15);
         
        // Printing the complex number
        System.out.println(c1);
    }
}
// Class 2
// Helper class
class Complex {
     
    // Attributes of a complex number
    private double re, im;
     

    public Complex(double re, double im) {
        this.re = re;
        this.im = im;
    }
    public double getReal() {
        return this.re;
    }
    public double getImaginary() {
        return this.im ;
    }
    public void setReal(double re) {
        this.re = re;
    }
    public void setImaginary(double im) {
        this.im = im;
    }
    // Overriding toString() method of String class
    @Override
    public String toString() {
        return this.re + " + " + this.im + "i";
    }
}
|   Complex.main(null);
cannot find symbol
  symbol:   method main(<nulltype>)