linked list in ruby

class Node
  attr_accessor :value, :next_node

  def initialize(value)
    @value = value
    @next_node = nil
  end
end

class LinkedList
  def initialize
    @head = nil
  end

  def append(value)
    if @head.nil?
      @head = Node.new(value)
    else
      current = @head
      while !current.next_node.nil?
        current = current.next_node
      end
      current.next_node = Node.new(value)
    end
  end

  def prepend(value)
    new_node = Node.new(value)
    new_node.next_node = @head
    @head = new_node
  end

  def size
    count = 0
    current = @head
    while !current.nil?
      count += 1
      current = current.next_node
    end
    count
  end

  def head
    @head
  end

  def tail
    current = @head
    while !current.next_node.nil?
      current = current.next_node
    end
    current
  end

  def at(index)
    current = @head
    count = 0
    while !current.nil?
      return current if count == index
      count += 1
      current = current.next_node
    end
    nil
  end

  def pop
    return nil if @head.nil?

    if @head.next_node.nil?
      value = @head.value
      @head = nil
      return value
    end

    current = @head
    previous = nil
    while !current.next_node.nil?
      previous = current
      current = current.next_node
    end

    value = current.value
    previous.next_node = nil
    value
  end

  def contains?(value)
    current = @head
    while !current.nil?
      return true if current.value == value
      current = current.next_node
    end
    false
  end

  def find(value)
    current = @head
    index = 0
    while !current.nil?
      return index if current.value == value
      index += 1
      current = current.next_node
    end
    nil
  end

  def to_s
    current = @head
    output = ''
    while !current.nil?
      output += "( #{current.value} ) -> "
      current = current.next_node
    end
    output += 'nil'
  end
end

# Example usage:
list = LinkedList.new
list.append(3)
list.append(5)
list.append(7)
list.prepend(1)
puts list.to_s  # Output: "( 1 ) -> ( 3 ) -> ( 5 ) -> ( 7 ) -> nil"
puts list.size  # Output: 4
puts list.head.value  # Output: 1
puts list.tail.value  # Output: 7
puts list.at(2).value  # Output: 5
puts list.pop  # Output: 7
puts list.to_s  # Output: "( 1 ) -> ( 3 ) -> ( 5 ) -> nil"
puts list.contains?(5)  # Output: true
puts list.find(3)  # Output: 1