Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package intra
- import java.io.PrintWriter
- import scala.collection.SortedSet
- import scala.collection.immutable.HashSet
- import scala.io.Source
- import scala.util.{Failure, Success, Using}
- case class Book(id: Int, value: Int)
- case class Library(id: Int, signUp: Int, capacity: Int, books: SortedSet[Book])
- case class FinalLibrary(id: Int, books: Vector[Int])
- object Tests extends Enumeration {
- case class Val(file: String) extends super.Val
- val A: Val = Val("a_example.txt")
- val B: Val = Val("b_read_on.txt")
- val C: Val = Val("c_incunabula.txt")
- val D: Val = Val("d_tough_choices.txt")
- val E: Val = Val("e_so_many_books.txt")
- val F: Val = Val("f_libraries_of_the_world.txt")
- }
- object Main {
- def main(args: Array[String]): Unit = {
- val (_, libraries, scanningDays) = read(Tests.A.file)
- val result = loop(libraries, HashSet.empty[Book], scanningDays, Vector.empty[FinalLibrary])
- write(result, Tests.A.file)
- }
- @annotation.tailrec
- def loop(libraries: Vector[Library], scanned: Set[Book], scanningDays: Int, result: Vector[FinalLibrary]): Vector[FinalLibrary] = {
- if (libraries.isEmpty || scanningDays <= 0) result else {
- val filtered = libraries.map(lib => lib.copy(books = lib.books.diff(scanned))).sortBy {
- library =>
- val taken = takenBooks(library, scanningDays)
- valueFunction(taken)
- }
- val first = filtered.head
- val books = takenBooks(first, scanningDays)
- val resLibrary = FinalLibrary(first.id, books.toVector.map(_.id))
- loop(filtered.tail, scanned ++ books, scanningDays - first.signUp, result :+ resLibrary)
- }
- }
- def magic(scanningDays: Int, signUp: Int, capacity: Int): Int = (scanningDays - signUp) * capacity
- def takenBooks(library: Library, scanningDays: Int): SortedSet[Book] = {
- val n = magic(scanningDays, library.signUp, library.capacity)
- library.books.take(n)
- }
- def valueFunction(books: SortedSet[Book]): Long = books.map(_.value).sum
- def read(file: String): (Vector[Book], Vector[Library], Int) = {
- Using(Source.fromFile(file)) { source =>
- val lines = source.getLines.toVector
- var currLine = 0
- def nextLine: String = {
- val line = lines(currLine)
- currLine += 1
- line
- }
- implicit def vectorOrdering: Ordering[Book] = (x: Book, y: Book) => y.value.compareTo(x.value)
- val booksCount :: librariesCount :: scanningDays :: Nil = nextLine.split(' ').map(_.toInt).toList
- val books = nextLine.split(' ').map(_.toInt).zipWithIndex.map { case (book, idx) => Book(idx, book) }
- val libraries = for (libraryIdx <- 0 until librariesCount) yield {
- val libraryBooksCount :: signUpDays :: booksPerDay :: Nil = nextLine.split(' ').map(_.toInt).toList
- val libraryBooks = nextLine.split(' ').map(_.toInt).map(books)
- Library(libraryIdx, signUpDays, booksPerDay, SortedSet.from(libraryBooks))
- }
- (books.toVector, libraries.toVector, scanningDays)
- }
- } match {
- case Failure(exception) => throw new IllegalStateException(s"Input parsing failed with exception $exception")
- case Success(value) => value
- }
- def write(vector: Vector[FinalLibrary], file: String): Unit = {
- Using(new PrintWriter("out_" + file)) { writer =>
- writer.println(vector.size)
- for (lib <- vector) {
- writer.println(s"${lib.id} ${lib.books.size}")
- writer.println(lib.books.mkString(" "))
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement