<commit_before>package game

import simulacrum.typeclass

/** Shape of a Go board. Should obey the law described in ShapeTests. */
@typeclass trait Shape[A] {
  def neighbours(a: A): Seq[A]
  def all: Seq[A]
}

object Shape {
  implicit val point19IsShape = new Shape[Point19] {
    def neighbours(p: Point19): Seq[Point19] =
      List((p.x + 1, p.y), (p.x - 1, p.y), (p.x, p.y + 1), (p.x, p.y - 1))
        .collect {
          case (a, b) if a >= 1 && a <= 19 && b >= 1 && b <= 19 =>
            Point19(a, b)
        }

    def all: Seq[Point19] =
      for { i <- 1 to 19; j <- 1 to 19 } yield Point19(i, j)
  }
}<commit_msg>Generalize point19IsShape<commit_after>package game

import simulacrum.typeclass
import scala.Function.unlift

/** Shape of a Go board. Should obey the law described in ShapeTests. */
@typeclass trait Shape[A] {
  def neighbours(a: A): Seq[A]
  def all: Seq[A]
}

object Shape {
  def unsafeIsShape[A](n: Int)(A: (Int, Int) => A, U: A => (Int, Int)): Shape[A] =
    new Shape[A] {
      def neighbours(a: A): Seq[A] = {
        val (x, y) = U(a)
        List((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1))
          .collect {
            case (a, b) if a >= 1 && a <= n && b >= 1 && b <= n =>
              A(a, b)
          }
      }

      def all: Seq[A] =
        for { i <- 1 to n; j <- 1 to n } yield A(i, j)
    }

  implicit val point19IsShape: Shape[Point19] =
    unsafeIsShape(19)(Point19.apply, unlift(Point19.unapply))
}
{'fraction_non_alphanumeric': 0.1720136518771331, 'fraction_numerical': 0.034129692832764506, 'mean_word_length': 2.2078774617067833, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2943879', 'n_tokens_mistral': 625, 'n_tokens_neox': 563, 'n_words': 179}