diff --git a/Lab Programs in Java 2024/1-GCD.java b/Lab Programs in Java 2024/1-GCD.java new file mode 100644 index 0000000..73a3a3d --- /dev/null +++ b/Lab Programs in Java 2024/1-GCD.java @@ -0,0 +1,87 @@ +import java.util.ArrayList; + +public class GCD { + + public static void main(String[] args) { + int n1 = 366, n2 = 60; + timefind(n1, n2); + } + + public static int euclid_hcf(int n1, int n2) { + if (n2 == 0) { + return n1; + } else { + int rem = n1 % n2; + return euclid_hcf(n2, rem); + } + } + + public static int consec_hcf(int a, int b) { + int cur_hcf = 1; + for (int i = 1; i <= b; i++) { + if (a % i == 0 && b % i == 0) { + cur_hcf = i; + } + } + return cur_hcf; + } + + public static int midsch_hcf(int a, int b) { + int cur_hcf = 1; + + ArrayList fac1 = new ArrayList(); + ArrayList fac2 = new ArrayList(); + + int c1 = 2; + int c2 = 2; + + while (a != 1) { + if ((a % c1) == 0) { + fac1.add(c1); + a = a / c1; + } else { + c1++; + } + } + + while (b != 1) { + if ((b % c2) == 0) { + fac2.add(c2); + b = b / c2; + } else { + c2++; + } + } + + for (Integer element : fac1) { + if (fac2.contains(element)) { + cur_hcf = cur_hcf * element; + fac2.remove(element); + } + } + return cur_hcf; + } + + public static void timefind(int a, int b) { + long startTime1 = System.nanoTime(); + int result1 = euclid_hcf(a, b); + long endTime1 = System.nanoTime(); + long executionTime1 = endTime1 - startTime1; + System.out.println("\nEuclid HCF: " + result1); + System.out.println("Execution time: " + executionTime1 + " nanoseconds"); + + long startTime2 = System.nanoTime(); + int result2 = consec_hcf(a, b); + long endTime2 = System.nanoTime(); + long executionTime2 = endTime2 - startTime2; + System.out.println("\nConsecutive HCF: " + result2); + System.out.println("Execution time: " + executionTime2 + " nanoseconds"); + + long startTime3 = System.nanoTime(); + int result3 = midsch_hcf(a, b); + long endTime3 = System.nanoTime(); + long executionTime3 = endTime3 - startTime3; + System.out.println("\nMid School HCF: " + result3); + System.out.println("Execution time: " + executionTime3 + " nanoseconds"); + } +} diff --git a/Lab Programs in Java 2024/10-Knapsack01.java b/Lab Programs in Java 2024/10-Knapsack01.java new file mode 100644 index 0000000..d6f3c89 --- /dev/null +++ b/Lab Programs in Java 2024/10-Knapsack01.java @@ -0,0 +1,34 @@ +public class Knapsack { + + // Function to solve the 0/1 Knapsack problem + public static int knapsack(int[] weights, int[] values, int capacity) { + int n = weights.length; + int[][] dp = new int[n + 1][capacity + 1]; + + // Build the DP table + for (int i = 0; i <= n; i++) { + for (int w = 0; w <= capacity; w++) { + if (i == 0 || w == 0) { + dp[i][w] = 0; + } else if (weights[i - 1] <= w) { + dp[i][w] = Math.max(values[i - 1] + dp[i - 1][w - weights[i - 1]], dp[i - 1][w]); + } else { + dp[i][w] = dp[i - 1][w]; + } + } + } + + return dp[n][capacity]; + } + + public static void main(String[] args) { + int[] weights = { 1, 3, 4, 5 }; + int[] values = { 1, 4, 5, 7 }; + int capacity = 7; + + // Calculate the maximum value that can be obtained + int maxValue = knapsack(weights, values, capacity); + // Print the maximum value + System.out.println("Maximum value in Knapsack = " + maxValue); + } +} diff --git a/Lab Programs in Java 2024/2-Binary Search.java b/Lab Programs in Java 2024/2-Binary Search.java new file mode 100644 index 0000000..47994ac --- /dev/null +++ b/Lab Programs in Java 2024/2-Binary Search.java @@ -0,0 +1,37 @@ +class BinarySearch { + + // Method to perform binary search + public static int binarySearch(int[] arr, int target) { + int left = 0; + int right = arr.length - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + + if (arr[mid] == target) { + return mid; // Target found, return its index + } + + if (arr[mid] < target) { + left = mid + 1; // Target is in the right half + } else { + right = mid - 1; // Target is in the left half + } + } + + return -1; // Target not found, return -1 + } + + public static void main(String[] args) { + int[] numbers = {1, 2, 5, 5, 6, 9}; // Array must be sorted for binary search + int target = 5; + + int result = binarySearch(numbers, target); + + if (result == -1) { + System.out.println("Target " + target + " not found in the array."); + } else { + System.out.println("Target " + target + " found at index " + result + "."); + } + } +} diff --git a/Lab Programs in Java 2024/2-Linear Search.java b/Lab Programs in Java 2024/2-Linear Search.java new file mode 100644 index 0000000..78e600a --- /dev/null +++ b/Lab Programs in Java 2024/2-Linear Search.java @@ -0,0 +1,25 @@ +class LinearSearch { + + // Method to perform linear search + public static int linearSearch(int[] arr, int target) { + for (int i = 0; i < arr.length; i++) { + if (arr[i] == target) { + return i; // Target found, return its index + } + } + return -1; // Target not found, return -1 + } + + public static void main(String[] args) { + int[] numbers = {5, 2, 9, 1, 5, 6}; + int target = 5; + + int result = linearSearch(numbers, target); + + if (result == -1) { + System.out.println("Target " + target + " not found in the array."); + } else { + System.out.println("Target " + target + " found at index " + result + "."); + } + } +} diff --git a/Lab Programs in Java 2024/3-QuickSort.java b/Lab Programs in Java 2024/3-QuickSort.java new file mode 100644 index 0000000..521f799 --- /dev/null +++ b/Lab Programs in Java 2024/3-QuickSort.java @@ -0,0 +1,78 @@ +import java.util.Random; + +public class QuickSort { + // Function to swap two elements + private static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + private static void quickSort(int[] arr, int low, int high) { + if (low < high) + { + // Call Partition function to find Partition Index + // int partitionIndex = partition(arr, low, high); + int pivot = arr[low]; + int i = low; + int j = high; + + while (i < j) { + // Condition 1: find the first element greater than the pivot (from starting) + while (arr[i] <= pivot && i <= high - 1) { + i++; + } + // Condition 2: find the first element smaller than the pivot (from last) + while (arr[j] > pivot && j >= low + 1) { + j--; + } + if (i < j) { + swap(arr, i, j); + } + } + swap(arr, low, j); + // Recursively call quickSort() for left and right half based on partition Index + quickSort(arr, low, j - 1); + quickSort(arr, j + 1, high); + } + } + + // Driver code + public static void main(String[] args) { + int n, l = 1; + long s, e; + double t; + + java.util.Scanner sc = new java.util.Scanner(System.in); + System.out.print("How many elements in array?: "); + n = sc.nextInt(); + int[] arr = new int[1000]; + Random rand = new Random(); + for (int i = 0; i < n; i++) { + // arr[i] = rand.nextInt(10) + 1; + arr[i] = rand.nextInt(n - l + 1); + } + + // Printing the original array + System.out.print("Original array: "); + for (int i = 0; i < n; i++) { + System.out.print(arr[i] + " "); + } + + // Calling quickSort() to sort the given array + s = System.nanoTime(); + quickSort(arr, 0, n - 1); + e = System.nanoTime(); + + // Printing the sorted array + System.out.print("\nSorted array: "); + for (int i = 0; i < n; i++) { + System.out.print(arr[i] + " "); + } + t = (double)(e - s) / 1_000_000_000; + System.out.printf("\nThe time taken by pivot at 1st position: %f seconds\n", t); + + sc.close(); + } +} + diff --git a/Lab Programs in Java 2024/4-MergeSort.java b/Lab Programs in Java 2024/4-MergeSort.java new file mode 100644 index 0000000..745d830 --- /dev/null +++ b/Lab Programs in Java 2024/4-MergeSort.java @@ -0,0 +1,76 @@ +import java.util.Arrays; + +public class MergeSort { + public static void main(String[] args) { + int[] array = {12, 11, 13, 5, 6, 7}; + System.out.println("Original array: " + Arrays.toString(array)); + + mergeSort(array, 0, array.length - 1); + + System.out.println("Sorted array: " + Arrays.toString(array)); + } + + public static void mergeSort(int[] array, int left, int right) { + + if(left==right) + { + //base case + return; + } + else{ + int mid = (left + right) / 2; + + mergeSort(array, left, mid); + mergeSort(array, mid + 1, right); + + //by the time we reach this line, only have singular nodes that have to be recursively merged together. + //so just before popping off the call stack, sort correctly and merge + merge(array, left, mid, right); + } + } + + public static void merge(int[] array, int left, int mid, int right) { + + //this code is the same as merging 2 sorted arrays + + int n1 = mid - left + 1; + //size of left subarray + + int n2 = right - mid; + // size fo right subarray + + int[] leftArray = new int[n1]; + int[] rightArray = new int[n2]; + + for (int i = 0; i < n1; i++) + leftArray[i] = array[left + i]; + for (int j = 0; j < n2; j++) + rightArray[j] = array[mid + 1 + j]; + + int i = 0, j = 0; + int k = left; + + while (i < n1 && j < n2) { + if (leftArray[i] <= rightArray[j]) { + array[k] = leftArray[i]; + i++; + } else { + array[k] = rightArray[j]; + j++; + } + k++; + } + + while (i < n1) { + array[k] = leftArray[i]; + i++; + k++; + } + + while (j < n2) { + array[k] = rightArray[j]; + j++; + k++; + } + } +} diff --git a/Lab Programs in Java 2024/5-DFS.java b/Lab Programs in Java 2024/5-DFS.java new file mode 100644 index 0000000..2b559ab --- /dev/null +++ b/Lab Programs in Java 2024/5-DFS.java @@ -0,0 +1,86 @@ +import java.util.*; + +class Node +{ + int val; + List nbs; //list of neighbours + + public Node(int val) + { + this.val=val; + this.nbs = new ArrayList<>(); + } + + public void addNbs(Node nb) + { + nbs.add(nb); + } +} + +class Graph +{ + List nodes; + + public Graph() + { + this.nodes = new ArrayList<>(); + } + + public void addNode(Node n) + { + nodes.add(n); + } +} + +class DFS +{ + public static void dfs(Node start) + { + Set visited = new HashSet<>(); + dfsRecursive(start,visited); + } + + private static void dfsRecursive(Node n,Set visited) + { + visited.add(n); + System.out.println("Visited node: " + n.val); + + for(Node x:n.nbs) + { + if(!visited.contains(x)) + { + dfsRecursive(x,visited); + } + } + } +} + +public class Main { + public static void main(String[] args) { + // Create nodes + Node node0 = new Node(0); + Node node1 = new Node(1); + Node node2 = new Node(2); + Node node3 = new Node(3); + Node node4 = new Node(4); + + // Create edges + node0.addNbs(node1); + node0.addNbs(node2); + node1.addNbs(node3); + node2.addNbs(node4); + + // Create graph + Graph graph = new Graph(); + graph.addNode(node0); + graph.addNode(node1); + graph.addNode(node2); + graph.addNode(node3); + graph.addNode(node4); + + // Perform DFS + System.out.println("DFS Traversal:"); + DFS.dfs(node0); + + } +} diff --git a/Lab Programs in Java 2024/6-BFS.java b/Lab Programs in Java 2024/6-BFS.java new file mode 100644 index 0000000..264e9d1 --- /dev/null +++ b/Lab Programs in Java 2024/6-BFS.java @@ -0,0 +1,84 @@ +import java.util.*; + +class Node +{ + int val; + List nbs; //list of neighbours + + public Node(int val) + { + this.val=val; + this.nbs = new ArrayList<>(); + } + + public void addNbs(Node nb) + { + nbs.add(nb); + } +} + +class Graph +{ + List nodes; + + public Graph() + { + this.nodes = new ArrayList<>(); + } + + public void addNode(Node n) + { + nodes.add(n); + } +} + +class BFS { + public static void bfs(Node start) { + Set visited = new HashSet<>(); + Queue queue = new LinkedList<>(); + + visited.add(start); + queue.offer(start); + + while (!queue.isEmpty()) { + Node current = queue.poll(); + System.out.println("Visited node: " + current.val); + + for (Node x : current.nbs) { + if (!visited.contains(x)) { + visited.add(x); + queue.offer(x); + } + } + } + } +} + + +public class Main { + public static void main(String[] args) { + // Create nodes + Node node0 = new Node(0); + Node node1 = new Node(1); + Node node2 = new Node(2); + Node node3 = new Node(3); + Node node4 = new Node(4); + + // Create edges + node0.addNbs(node1); + node0.addNbs(node2); + node1.addNbs(node3); + node2.addNbs(node4); + + // Create graph + Graph graph = new Graph(); + graph.addNode(node0); + graph.addNode(node1); + graph.addNode(node2); + graph.addNode(node3); + graph.addNode(node4); + + System.out.println("BFS Traversal:"); + BFS.bfs(node0); + } +} diff --git a/Lab Programs in Java 2024/7-TopologicalSort.java b/Lab Programs in Java 2024/7-TopologicalSort.java new file mode 100644 index 0000000..24d0388 --- /dev/null +++ b/Lab Programs in Java 2024/7-TopologicalSort.java @@ -0,0 +1,75 @@ +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; +import java.util.Stack; + +class Node { + int data; + ArrayList nbs; + + public Node(int val) { + this.data = val; + this.nbs = new ArrayList<>(); + } + + public void addNbs(Node x) { + this.nbs.add(x); + } +} + +class DFS { + Stack tps = new Stack<>(); + Set visit = new HashSet<>(); + + public void topoSort(Node s) { + if (!visit.contains(s)) { + visit.add(s); + for (Node x : s.nbs) { + topoSort(x); + } + tps.push(s); // Push 's' after processing its neighbors + } + } + + public void printTopoSort() { + while (!tps.empty()) { + System.out.println(tps.pop().data); + } + } + + // this function is here to find inflection points - the nodes in the graph other than the source whose indegree is 0 + //i.e, they are disconnected from our original graph + public void topoSortAll(Node[] nodes) { + for (Node node : nodes) { + if (!visit.contains(node)) { // Skip nodes that have been visited + topoSort(node); + } + } + } +} + +public class Main { + public static void main(String[] args) { + // Create nodes + Node node1 = new Node(1); + Node node2 = new Node(2); + Node node3 = new Node(3); + Node node4 = new Node(4); + Node node5 = new Node(5); + Node node0 = new Node(0); + + // Create edges + node2.addNbs(node3); + node3.addNbs(node1); + node4.addNbs(node0); + node4.addNbs(node1); + node5.addNbs(node0); + node5.addNbs(node2); + + // Example usage + DFS dfs = new DFS(); + Node[] nodes = {node0, node1, node2, node3, node4, node5}; + dfs.topoSortAll(nodes); + dfs.printTopoSort(); + } +} diff --git a/Lab Programs in Java 2024/8-PrimsAlgorithm.java b/Lab Programs in Java 2024/8-PrimsAlgorithm.java new file mode 100644 index 0000000..197d45e --- /dev/null +++ b/Lab Programs in Java 2024/8-PrimsAlgorithm.java @@ -0,0 +1,173 @@ +import java.util.*; + +// the idea +// visit start first and add all its neigbouring edges. this step is done only once, in the beginning + +//now comes the main part +// we need to repeatedly look into the priority queue, obtain the minimum length edge using pop +// we know the edge and its weight, but we dont know anything about the vertices. +// so check whether this edge will form a loop - check if both its extrema vertices are already visited, +// if yes, we cannot include it in our solution +// if not, add it to the MST(that was the only thing we needed to worry about!!) + +// now, obviously, we just checked that both the nodes were unvisited, i.e. either node1 is visited or node2 is visited +// both cannot be visited. so now simply visit the one we havent visited!! + +// doing this, we can cover the entire graph. + +class Node { + //each node has a value + String val; + //then it has a list of edges, which itself are objects. the name of this list is nbs - neighbours + List nbs; // list of edges to neighbors + + //constructor to construct the node + public Node(String val) { + this.val = val; + this.nbs = new ArrayList <> (); + } + + //addEdge function creates a new edge by calling the constructor of edge class which takes from which node , + //to which node and weight of the edge, and adds it to the nbs list + public void addEdge(Node neighbor, int weight) { + this.nbs.add(new Edge(this, neighbor, weight)); + } +} + +class Edge { + //edge has the properties : from which node , + // to which node and weight of the edge, and adds it to the nbs list + Node from; + Node to; + int weight; + + //constructor - which was called when we wanted to add edge for a node + public Edge(Node from, Node to, int weight) { + this.from = from; + this.to = to; + this.weight = weight; + } +} + +class Graph { + //graph is simply a list of nodes + List nodes; + + public Graph() { + this.nodes = new ArrayList <> (); + } + + public void addNode(Node n) { + nodes.add(n); + } + + // Function to add weighted edge + public void addEdge(Node from, Node to, int weight) { + from.addEdge(to, weight); + to.addEdge(from, weight); // Assuming undirected graph + } + + // Prim's algorithm to find Minimum Spanning Tree (MST) + public List primMST(Node start) { + // Set to keep track of visited nodes + Set visited = new HashSet <> (); + + // List to store edges of the Minimum Spanning Tree (MST) + List mst = new ArrayList <> (); + + // Priority queue to store edges sorted by weight + PriorityQueue minHeap = new PriorityQueue <> (Comparator.comparingInt(e -> e.weight)); + + // Start the Prim's algorithm by visiting the start node + + //visit function, basically just adds current node to visited and all it neighbouring edges , which are pointing to unvisited nodes, into the priorityqueue + visit(start, visited, minHeap); + + // Continue until all nodes are visited or priority queue is empty + while (!minHeap.isEmpty()) { + // Extract the edge with the smallest weight from the priority queue + Edge edge = minHeap.poll(); + + // Nodes at either ends of the edge that we got from the above min poll + Node u = edge.from; + Node v = edge.to; + + // If both nodes are already visited, which indicates the formation of a cycle, skip this edge + if (visited.contains(u) && visited.contains(v)) { + continue; + } + + // Add the edge to the MST + mst.add(edge); + + // Determine the next node to visit + Node next = visited.contains(u) ? v : u; + + // Visit the next node + visit(next, visited, minHeap); + } + + // Return the Minimum Spanning Tree (MST) edges + return mst; + } + + // Helper method to visit a node and add its edges to the priority queue + private void visit(Node node, Set visited, PriorityQueue minHeap) { + // Mark the node as visited + visited.add(node); + + // Iterate through all edges of the current node + for (Edge edge: node.nbs) { + // If the edge leads to an unvisited node, add it to the priority queue + if (!visited.contains(edge.to)) { + minHeap.offer(edge); + } + } + } + +} + +public class Main { + public static void main(String[] args) { + // Create nodes + Node nodeA = new Node("A"); + Node nodeB = new Node("B"); + Node nodeC = new Node("C"); + Node nodeD = new Node("D"); + Node nodeE = new Node("E"); + Node nodeF = new Node("F"); + + + // Create graph + Graph graph = new Graph(); + graph.addNode(nodeA); + graph.addNode(nodeB); + graph.addNode(nodeC); + graph.addNode(nodeD); + graph.addNode(nodeE); + graph.addNode(nodeF); + + + // Create weighted edges + graph.addEdge(nodeF, nodeE, 8); + graph.addEdge(nodeD, nodeE, 3); + graph.addEdge(nodeF, nodeD, 7); + graph.addEdge(nodeD, nodeA, 6); + graph.addEdge(nodeE, nodeA, 4); + graph.addEdge(nodeE, nodeC, 3); + graph.addEdge(nodeA, nodeC, 2); + graph.addEdge(nodeC, nodeB, 2); + graph.addEdge(nodeA, nodeB, 5); + + // Perform Prim's algorithm to find MST + List mst = graph.primMST(nodeF); + + // Print MST edges + System.out.println("Minimum Spanning Tree (MST) using Prim's Algorithm:"); + for (Edge edge: mst) { + System.out.println(edge.from.val + " - " + edge.to.val + " : " + edge.weight); + } + } +} + + diff --git a/Lab Programs in Java 2024/9-DijkstrasAlgo.java b/Lab Programs in Java 2024/9-DijkstrasAlgo.java new file mode 100644 index 0000000..179fbdf --- /dev/null +++ b/Lab Programs in Java 2024/9-DijkstrasAlgo.java @@ -0,0 +1,138 @@ +import java.util.*; + +// idea +// basically, we want the minimum distance between source and every vertex in the graph +// we give a dist parameter to each node, which we update at every relaxation +// first we set dist from src to src as 0 and everything else as INF +// then, for each neighbour of src, relax the distance + +// unlike prims, here our minheap stores the node and not the edge +// in general, the idea is, every time we do a relaxation step, we add that node to minheap +// this is for 2 reasons +// 1. we are greedy: we want the shortest path, and at every relaxation the path which is shortest is picked to traverse +// 2. path shrinks: once the relaxation occurs, if a path to already visited node relaxes, then overall path length also decreases +// this is the reason why the same node may enter the minheap multiple times and we are not concerned about visited state + +// Node class represents a node in the graph +class Node { + int val; // Node value + List nbs; // List of edges (neighbors) + int dist; // Distance from the source node + + // Constructor to initialize a node with a value + public Node(int val) { + this.val = val; + this.nbs = new ArrayList<>(); + this.dist = Integer.MAX_VALUE; + } + + // Method to add a neighbor (edge) to the node with a specified weight + public void addEdge(Node neighbor, int weight) { + nbs.add(new Edge(this, neighbor, weight)); + } +} + +// Edge class represents an edge between two nodes with a weight +class Edge { + Node from; // Starting node of the edge + Node to; // Ending node of the edge + int weight; // Weight of the edge + + // Constructor to initialize an edge with starting node, ending node, and weight + public Edge(Node from, Node to, int weight) { + this.from = from; + this.to = to; + this.weight = weight; + } +} + +// Graph class represents a collection of nodes and edges +class Graph { + List nodes; // List of nodes in the graph + + // Constructor to initialize an empty graph + public Graph() { + this.nodes = new ArrayList<>(); + } + + // Method to add a node to the graph + public void addNode(Node n) { + nodes.add(n); + } + + // Method to add a weighted edge between two nodes in the graph + public void addEdge(Node from, Node to, int weight) { + from.addEdge(to, weight); + // Assuming undirected graph, adding both directions + to.addEdge(from, weight); + } + + // Dijkstra's algorithm to find shortest path from start node to all nodes + public void dijkstra(Node start) { + // Priority queue to fetch nodes with the smallest known distance + PriorityQueue minHeap = new PriorityQueue<>(Comparator.comparingInt(n -> n.dist)); + + // Initialize distances of all nodes as infinity + for (Node node : nodes) { + node.dist = Integer.MAX_VALUE; + } + + // Distance from start node to itself is 0 + start.dist = 0; + minHeap.offer(start); + + // Process nodes in the priority queue until it is empty + while (!minHeap.isEmpty()) { + // Extract the node with the smallest distance from the priority queue + Node u = minHeap.poll(); + + // Iterate through all neighboring edges of the current node + for (Edge edge : u.nbs) { + Node v = edge.to; + int weight = edge.weight; + int newDist = u.dist + weight; + + // If a shorter path to node v is found, update its distance and add to the priority queue + if (newDist < v.dist) { + v.dist = newDist; + minHeap.offer(v); + } + } + } + } +} + +// Main class for testing Dijkstra's algorithm +public class Main { + public static void main(String[] args) { + // Create nodes + Node node0 = new Node(0); + Node node1 = new Node(1); + Node node2 = new Node(2); + Node node3 = new Node(3); + Node node4 = new Node(4); + + // Create graph + Graph graph = new Graph(); + graph.addNode(node0); + graph.addNode(node1); + graph.addNode(node2); + graph.addNode(node3); + graph.addNode(node4); + + // Create weighted edges + graph.addEdge(node0, node1, 2); + graph.addEdge(node0, node2, 3); + graph.addEdge(node1, node3, 4); + graph.addEdge(node2, node4, 1); + + // Perform Dijkstra's algorithm from node0 + graph.dijkstra(node0); + + // Print shortest distances + System.out.println("Shortest distances from node " + node0.val + ":"); + for (Node node : graph.nodes) { + System.out.println("To node " + node.val + ": " + node.dist); + } + } +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy