diff --git a/src/main/java/com/thealgorithms/datastructures/lists/SelfOrganizingLinkedList.java b/src/main/java/com/thealgorithms/datastructures/lists/SelfOrganizingLinkedList.java new file mode 100644 index 000000000000..341f6e8b039b --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/lists/SelfOrganizingLinkedList.java @@ -0,0 +1,127 @@ +package com.thealgorithms.datastructures.lists; + +import java.util.Objects; + + + +/** + * Node structure for the generic linked list. + * + * @param the type of element held in this node + */ +class LinkedList { + E value; + LinkedList next; + + public LinkedList(E value) { + this.value = value; + this.next = null; + } +} + + +/** + * A Self-Organizing Linked List implementation using the Move-To-Front (MTF) strategy. + * When an element is searched, it is automatically moved to the head of the list + * to optimize subsequent lookups. + * + * @param the type of elements held in this list + */ + +public class SelfOrganizingLinkedList{ + private LinkedList head; + private int size; + + public SelfOrganizingLinkedList(){ + this.size=0; + this.head=null; + } + + /** + * Inserts a new value at the end of the list. + * + * @param value the item to insert + */ + + public void insert(E value){ + LinkedList newNode=new LinkedList<>(value); + if (head == null) { + head = newNode; + } else { + LinkedList temp = head; + while (temp.next != null) { + temp = temp.next; + } + temp.next = newNode; + } + size++; + + } + + /** + * Searches for a value in the list. + * If found, moves the node to the front (head) of the list. + * + * @param key the value to search for + * @return true if the element is present, false otherwise + */ + public boolean search(E key) { + if (head == null) { + return false; + } + + + if (Objects.equals(head.value, key)) { + return true; + } + + LinkedList prev = null; + LinkedList curr = head; + + + while (curr != null && !Objects.equals(curr.value, key)) { + prev = curr; + curr = curr.next; + } + + + if (curr == null) { + return false; + } + + + prev.next = curr.next; + curr.next = head; + head = curr; + + return true; + } + + /** + * Gets the current head of the list. + * + * @return value at head, or null if list is empty + */ + public E getHeadValue() { + return head != null ? head.value : null; + } + + /** + * Returns the size of the list. + * + * @return number of elements + */ + public int getSize() { + return size; + } + + /** + * Returns true if the list contains no elements. + * + * @return true if empty + */ + public boolean isEmpty() { + return head == null; + } +} + diff --git a/src/main/java/com/thealgorithms/maths/DisariumNumber.java b/src/main/java/com/thealgorithms/maths/DisariumNumber.java new file mode 100644 index 000000000000..0196d0797bcc --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/DisariumNumber.java @@ -0,0 +1,37 @@ +package com.thealgorithms.maths; + +/** + * Disarium number is a number where the sum of its digits powered + * with their respective positions is equal to the number itself. + * Example: 135 = 1^1 + 3^2 + 5^3 = 1 + 9 + 125 = 135 + * + * @see Disarium Number + */ +public final class DisariumNumber { + + private DisariumNumber() { + } + + /** + * Checks if a number is a Disarium number. + * + * @param number the number to check (must be positive) + * @return true if number is Disarium, false otherwise + * @throws IllegalArgumentException if number is not positive + */ + public static boolean isDisarium(int number) { + if (number <= 0) { + throw new IllegalArgumentException("Input must be a positive integer."); + } + int digits = String.valueOf(number).length(); + int temp = number; + int sum = 0; + while (temp > 0) { + int lastDigit = temp % 10; + sum += (int) Math.pow(lastDigit, digits); + digits--; + temp /= 10; + } + return sum == number; + } +} diff --git a/src/test/java/com/thealgorithms/datastructures/lists/SelfOrganizingLinkedListTest.java b/src/test/java/com/thealgorithms/datastructures/lists/SelfOrganizingLinkedListTest.java new file mode 100644 index 000000000000..f030c3daf261 --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/lists/SelfOrganizingLinkedListTest.java @@ -0,0 +1,86 @@ +package com.thealgorithms.datastructures.lists; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class SelfOrganizingLinkedListTest { + private SelfOrganizingLinkedList list; + + @BeforeEach + void setUp() { + list = new SelfOrganizingLinkedList<>(); + } + + @Test + void testSearchOnEmptyList() { + assertFalse(list.search(10)); + assertNull(list.getHeadValue()); + } + + @Test + void testSearchElementAtHeadValueDoesNotChangeStructure() { + list.insert(10); + list.insert(20); + list.insert(30); + + assertTrue(list.search(10)); + assertEquals(10, list.getHeadValue()); + } + + @Test + void testMoveMiddleElementToFront() { + list.insert(10); + list.insert(20); + list.insert(30); + list.insert(40); + + // Search middle element '30' + assertTrue(list.search(30)); + + // '30' should now be the new head + assertEquals(30, list.getHeadValue()); + } + + @Test + void testMoveLastElementToFront() { + list.insert(10); + list.insert(20); + list.insert(30); + + // Search last element '30' + assertTrue(list.search(30)); + + assertEquals(30, list.getHeadValue()); + } + + @Test + void testSearchNonExistentElement() { + list.insert(10); + list.insert(20); + + assertFalse(list.search(99)); + assertEquals(10, list.getHeadValue()); // Head remains unchanged + } + + @Test + void testMultipleSearchesSequentialMoveToFront() { + list.insert(1); + list.insert(2); + list.insert(3); + + list.search(2); // Head becomes 2 + assertEquals(2, list.getHeadValue()); + + list.search(3); // Head becomes 3 + assertEquals(3, list.getHeadValue()); + + list.search(1); // Head becomes 1 + assertEquals(1, list.getHeadValue()); + } + + +} diff --git a/src/test/java/com/thealgorithms/maths/DisariumNumberTest.java b/src/test/java/com/thealgorithms/maths/DisariumNumberTest.java new file mode 100644 index 000000000000..54e9e861ad44 --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/DisariumNumberTest.java @@ -0,0 +1,32 @@ +package com.thealgorithms.maths; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class DisariumNumberTest { + + @Test + void testDisariumNumbers() { + assertTrue(DisariumNumber.isDisarium(1)); + assertTrue(DisariumNumber.isDisarium(89)); + assertTrue(DisariumNumber.isDisarium(135)); + assertTrue(DisariumNumber.isDisarium(175)); + assertTrue(DisariumNumber.isDisarium(518)); + } + + @Test + void testNonDisariumNumbers() { + assertFalse(DisariumNumber.isDisarium(10)); + assertFalse(DisariumNumber.isDisarium(100)); + assertFalse(DisariumNumber.isDisarium(200)); + } + + @Test + void testInvalidInput() { + assertThrows(IllegalArgumentException.class, () -> DisariumNumber.isDisarium(0)); + assertThrows(IllegalArgumentException.class, () -> DisariumNumber.isDisarium(-5)); + } +}