Попытка Pattern сопоставить целочисленный аргумент «глобально» внутри функции - Scala - PullRequest
0 голосов
/ 07 марта 2020

Прежде всего, я прошу прощения, если название этого сообщения вводит в заблуждение, оно основано на том, что я думаю, может быть моей проблемой. Я создаю ленивый список кортежей, конечная цель - найти всех пифагорейских троек со значениями, меньшими или равными n, и вместо того, чтобы создавать все возможные комбинации «троек», я выбрал этот подход который я считаю более эффективным, но может быть излишним, однако, это работает:)

  val n = 20
  val increasingTriplets  = unfold(Option(1, 1, 1)) {
    case None => None
    case Some(current) =>
      val maybeNext = current match {
        case (`n`, `n`, `n`) => None
        case (x, `n`, `n`) => Some(x + 1, x + 1, x + 1)
        case (x, y, `n`) => Some(x, y + 1, y + 1)
        case (x, y, z) => Some(x, y, z + 1) // (1,1,1) , (1,1,2), (1,1,3)...etc
      }
      Some(current, maybeNext)
  }.take(nCr(`n`+3-1,3).toInt).filter({ // The formula for the number of combinations with repetition -
    case (a,b,c) => a*a + b*b == c*c    // - allowed of ? objects from ? types is  ?+?−1C?
                                       // Ensures minimum number of lists is always generated(I think)
  })    

    println(unfold_with_pythcomp(increasingTriplets,pythcomp).toList)
    // n = 20 List((3,4,5), (4,3,5), (5,12,13), (12,5,13), (6,8,10)
    List((3,4,5), (4,3,5), (5,12,13), (12,5,13), (6,8,10), (8,6,10),
   (8,15,17), (15,8,17), (9,12,15), (12,9,15), (12,16,20), (16,12,20))

    // n = 10
    List((3,4,5), (4,3,5), (6,8,10), (8,6,10))


  // Implementation of unfold

  def unfold[A, S](z: S)(f: S => Option[(A, S)]): LazyList[A] =
    f(z).map((p: (A, S)) => p._1 #:: unfold(p._2)(f)).getOrElse(LazyList.empty[A])

  def unfold_with_pythcomp[A](l1: LazyList[A], f: A => Option[(A, A)]): LazyList[A] =
  // unfolds result list appending the "complement"
    l1 match {
      case LazyList() => l1
      case x #:: y => f(x) match {
        case Some((l, r)) => l #:: r #:: unfold_with_pythcomp(y, f)
      }
    }

  def pythcomp(t: (Int, Int, Int)): Option[((Int, Int, Int), (Int, Int, Int))] = t match {
      //Creates a "complement" to add since (3,4,5) <-> (4,3,5)
    case (a, b, c) => Some((a, b, c), (b, a, c))
  }

  def fact(n: Int): BigInt = { // These are just for efficiency, you may ignore
    @tailrec def go(n: Int, acc: BigInt): BigInt =
      if (n <= 0) acc
      else go(n - 1, BigInt(n) * acc)
    go(n, 1)

  }
  def nCr(n: Int, r: Int): BigInt = { // These are just for efficiency, you may ignore
    fact(n)/(fact(n-r) * fact(r))
  }

Теперь я пытаюсь превратить это в функцию, которая будет делать то же самое, пока принимая просто n в качестве аргумента, который может быть очень простым, однако я столкнулся с проблемами, пытаясь сопоставить шаблон с данным n аргументом. Это то, что я придумал до сих пор:

  def unfold_remix[Int](`n`: Int): LazyList[Option[(Int, Int, Int)]] =
  // not sure if I can use backticks here
    unfold(Option(1, 1, 1)) {
      case None => None
      case Some(current) =>
        // Problem could also be from here.
        val maybeNext = current match {
          case (`n`, `n`, `n`) => None
          case (x, `n`, `n`) => Some(x + 1, x + 1, x + 1)
          case (x, y, `n`) => Some(x, y + 1, y + 1)
          case (x, y, z) => Some(x, y, z + 1) // (1,1,1) , (1,1,2), (1, 1,3)...1st
        }
        Some(current, **maybeNext**)
      // I get an error on this line under maybeNext.
      // Too many arguments for method apply(A)
    }

Я продолжаю получать сообщение об ошибке при попытке инициализировать список, как я делал ранее, и будучи новичком в Scala Я не могу понять, Почему. Я попробовал аргумент с и без обратной галочки, и это тоже не сработало. Интересно, можно ли кому-нибудь помочь мне разобраться в проблеме, а также мне хотелось бы знать, возможно ли сопоставить шаблон с целочисленным аргументом «глобально» внутри функции. Спасибо!

1 Ответ

1 голос
/ 07 марта 2020

Не знаю, возвращает ли это правильные результаты, но компилируется (проверка типов).

def unfold_remix(n: Int): LazyList[Option[(Int, Int, Int)]] =
  unfold(Option(1, 1, 1)) {
    case None => None
    case Some(current) =>
      val maybeNext = current match {
        case (`n`, `n`, `n`) => None
        case (x, `n`, `n`) => Some(x + 1, x + 1, x + 1)
        case (x, y, `n`) => Some(x, y + 1, y + 1)
        case (x, y, z) => Some(x, y, z + 1)
      }
      Some((Some(current), maybeNext))
  }

(И да, это слишком много кода для относительно простой задачи.)

...