Codility TapeEquilibrium Scala

时间:2014-02-11 01:46:56

标签: scala

我使用Scala编写了一个关于Codility的TapeEquilibrium问题的解决方案。我尝试了不同负载的大量测试输入,当我使用Codility Develipment环境和eclipse运行结果时,我得到了正确的答案。但是,当我提交结果时,几乎每次测试都会失败,并且错误的答案。我无法掌握确切的输入,但我已经使用随机数生成了类似大小的输入,这些输入始终有效。我已经查看了一段时间的逻辑,但无法弄清楚我做错了什么。有人能帮我吗。

可以找到测试here

这是我的代码

import org.scalacheck.Gen
import org.scalacheck._

object Problem1 extends App {

  def solution( A: Array[ Int ] ): Int = {
    var sumRight = A.foldLeft( 0 )( _ + _ )
    var sumLeft = 0;
    def absDiffer( a: Int, b: Int ) = if ( a < b ) b - a else a - b

    def minimizer( ar: List[ Int ], prevDiff: Int, sumL: Int, sumR: Int ): Int = {
      val diff = absDiffer( sumL, sumR )
      if ( diff <= prevDiff )
        minimizer( ar.tail, diff, ar.head + sumL, sumR - ar.head )
      else
        prevDiff
    }
    minimizer( A.toList, absDiffer( A.head, sumRight - A.head ), A.head, sumRight - A.head )
  }
  def randomInput( length: Int ) = {
    Gen.listOfN( length, Gen.oneOf( Range( -1000, 1000 ) ) ).sample.get
  }
  def randomPosInput( length: Int ) = {
    Gen.listOfN( length, Gen.oneOf( Range( 1, 100 ) ) ).sample.get
  }
  def randomNegInput( length: Int ) = {
    Gen.listOfN( length, Gen.oneOf( Range( -1000, -1 ) ) ).sample.get
  }

  val ar = randomPosInput( 100000 )
  val inputString = ar.mkString( "[", ", ", "]" )
  val clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard()
  val sel = new java.awt.datatransfer.StringSelection( inputString )
  clipboard.setContents( sel, sel )
  println( inputString )
  println( solution( ar.toArray ) )
}

6 个答案:

答案 0 :(得分:4)

我不是Scala开发人员,但我认为你过早地结束了你的递归 -

if ( diff <= prevDiff )
    minimizer( ar.tail, diff, ar.head + sumL, sumR - ar.head )
else
    prevDiff

我相信这应该是:

if ( diff <= prevDiff )
    minimizer( ar.tail, diff, ar.head + sumL, sumR - ar.head )
else
    minimizer( ar.tail, prevDiff, ar.head + sumL, sumR - ar.head )

并且最后需要选择总体最小差异。

不确定这是否有帮助,但这是我在JS(100/100 on Codility)中共同攻击的解决方案:

function solution(A) {
    var total, forward, test, best;
    total = 0;
    for (var i = 0; i < A.length; i++) {
        total += A[i];
    }
    forward = A[0];
    best = Math.abs(total - 2*forward);
    for (i = 1; i < A.length-1; i++) {
        forward += A[i];
        test = Math.abs(total - 2*forward);
        if (test < best) {
            best = test;
        }
    }
    return best;
}

答案 1 :(得分:3)

我想出了Scala中的以下解决方案(获得100%)

import scala.collection.JavaConversions._

object Solution {
    def solution(A: Array[Int]): Int = {
        def diffAbs(a: Int, b: Int): Int = if (a - b < 0) b - a else a - b
        def findDiff(list: List[Int], leftSum: Int, rightSum: Int, diff: Int): Int = {
            list match {
                case x1 :: x2 :: xs => 
                val curDiff = diffAbs(leftSum, rightSum)
                val bestDiff = if (curDiff < diff) curDiff else diff
                findDiff(list.tail, leftSum + x1, rightSum - x1, bestDiff)
                case _ => diff
            }
        }
        val leftSum: Int = A(0)
        val rightSum: Int = A.foldLeft(0)(_ + _) - A(0)
        val diff = diffAbs(leftSum, rightSum)
        findDiff(A.toList.tail, leftSum, rightSum, diff)
    }

}

答案 2 :(得分:2)

我在Scala中得到了100%,这是我的解决方案:http://geeks.aretotally.in/codility-tapeequilibrium-in-scala/

import scala.math.{min, abs}

object Solution {  
    def solution(A: Array[Int]): Int = {
      if (A.size < 2 || A.size > 100000) sys.error(s"Invalid input - array size: ${A.size}")

      val total = A.map(_.toLong).sum

      (A.foldLeft[(Int, Long, Long)](-1, -1, 0l) { (t, i) =>
        if (i < -1000 || i > 1000) sys.error(s"Invalid array element: $i")

        val (x, currentMin, lastLeftSum) = t
        val index = x + 1

        (index + 1 == A.size) match {
          case true =>
            // Do nothing on the last element
            t

          case false =>
            val leftSum = lastLeftSum.toLong + A(index).toLong
            val rightSum = total - leftSum

            val thisMin = abs(leftSum- rightSum)
            val results = if (currentMin == -1) thisMin
            else min(currentMin, thisMin)

            (index, results, leftSum)
        }

      })._2.toInt
    }
}

答案 3 :(得分:1)

100/100 php解决方案在这里:http://www.rationalplanet.com/php-related/tapeequilibrium-demo-task-at-codility-com.html

function solution($A) {
    $sum1   = $A[0];
    $sum2   = array_sum($A) - $sum1;
    $found  = array('index'=>0, 'abs' => abs($sum1 - $sum2));
    $c = count($A) - 1;
    $i = 1;
    while($i < $c){
        $sum1 += $A[$i];
        $sum2 -= $A[$i];
        $abs = abs($sum1 - $sum2);
        if($abs < $found['abs']){
            $found['index'] = $i;
            $found['abs'] = $abs;
        }
        $i++;
    }  
    return $found['abs'];
}

答案 4 :(得分:0)

 def solution(list: Array[Int]): Int = {
    val sum = list.sum
    var min = Integer.MAX_VALUE
    list.reduceLeft {(sumLeft, current) =>
      min = Math.min(min, Math.abs(sumLeft - (sum - sumLeft)))
      sumLeft + current
    }
    min
  }

正确但不相信这是一个功能性解决方案:(

答案 5 :(得分:0)

JAVA解决方案100%

public int solution(int[] A) {

        int left = A[0];
        int right = 0;

        for(int i: A){
            right += i;
        }

        right -= left;

        int diff = Math.abs(left - right);
        for (int i = 1; i < A.length-1; i++) {
            left += A[i];
            right -= A[i];
            int a = Math.abs(left - right);
            if(diff > a){
                diff = a;
            }
        }
        return diff;
}