Library Lending with Classes

Problem

A library has books. Commands: add TITLE (print added, or exists if the title is already there), borrow TITLE USER (print borrowed, or not available if somebody has it), return TITLE (print returned, or not borrowed if it is on the shelf), who TITLE (print the user who has the book, or shelf). If the title is unknown, every command except add prints no such book.

Constraints

  • 1 <= commands <= 100
  • TITLE and USER have no spaces

Examples

Input

add java
borrow java amit
who java

Output

added
borrowed
amit

Solutions

Best approachTime O(n)Space O(n)

Each class owns its rules: the Book knows if it can be lent, the Library knows which books exist. The commands only call methods and never touch the fields of a book directly.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Run the library.
 * Input   : Command lines.
 * Output  : One answer line per command.
 * Approach: Book and Library classes
 * Time    : O(n)
 * Space   : O(n)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: A Book knows its own state: who has it (null means it is on the shelf).
        static class Book {
            final String title;
            String holder;

            Book(String title) {
                this.title = title;
            }

            // Step 2: The book guards its own rules.
            boolean lend(String user) {
                if (holder != null) {
                    return false;
                }
                holder = user;
                return true;
            }

            boolean giveBack() {
                if (holder == null) {
                    return false;
                }
                holder = null;
                return true;
            }
        }

        // Step 3: The Library owns the books and answers the commands.
        static class Library {
            private final java.util.Map<String, Book> books = new java.util.HashMap<>();

            String run(String[] part) {
                if (part[0].equals("add")) {
                    if (books.containsKey(part[1])) {
                        return "exists";
                    }
                    books.put(part[1], new Book(part[1]));
                    return "added";
                }
                Book book = books.get(part[1]);
                if (book == null) {
                    return "no such book";
                }
                if (part[0].equals("borrow")) {
                    return book.lend(part[2]) ? "borrowed" : "not available";
                }
                if (part[0].equals("return")) {
                    return book.giveBack() ? "returned" : "not borrowed";
                }
                return book.holder == null ? "shelf" : book.holder;
            }
        }

    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        Library library = new Library();
        String[] out = new String[lines.length];
        for (int i = 0; i < lines.length; i++) {
            out[i] = library.run(lines[i].split(" "));
        }
        return out;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        java.util.List<String> all = new java.util.ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                all.add(line);
            }
        }
        String[] lines = all.toArray(new String[0]);
        System.out.println(String.join("\n", solve(lines)));
    }
}
Hints (1)
  1. Which class decides if a book can be lent?