Tiếp theo là gì?


15

Đưa ra một danh sách các số nguyên được phân tách bằng dấu cách, nhiệm vụ của bạn là tìm số nguyên tiếp theo trong chuỗi. Mỗi số nguyên trong dãy là kết quả của việc áp dụng một phép toán đơn ( +, -, *hoặc /) đến số nguyên trước, và mỗi dãy được tạo thành từ một số biến của các hoạt động đó (nhưng không quá 10). Không có chuỗi nào sẽ dài hơn một nửa độ dài của chuỗi số nguyên, vì vậy bạn sẽ có mỗi chuỗi hoạt động xuất hiện ít nhất hai lần để xác nhận.
Đầu vào sẽ thông qua stdin (hoặc promptcho các giải pháp JavaScript).

Dưới đây là một số ví dụ giải thích.

Đầu vào:

1 3 5 7 9 11

Đầu ra:

13

Khá dễ dàng, cái này. Tất cả các giá trị là giá trị trước đó +2.

Đầu vào:

1 3 2 4 3 5 4 6 5 7 6

Ouput:

8

Hai bước trong chuỗi này, +2sau đó -1.

Đầu vào:

2 6 7 3 9 10 6 18 19 15 45 46

Đầu ra:

42

Ba bước - *3, +1, -4.

Các trường hợp thử nghiệm

Dưới đây là một vài trường hợp thử nghiệm:

Đầu vào:

1024 512 256 128 64 32 16

Đầu ra:

8

Đầu vào:

1 3 9 8 24 72 71 213 639

Đầu ra:

638

Đầu vào:

1 2 3 4 5 2 3 4 5 6 3 4 5 6 7

Đầu ra:

4

Đầu vào:

1 2 4 1 3 9 5 8 32 27 28 56 53 55 165 161 164 656 651 652 1304

Đầu ra:

1301

Tôi có một giải pháp Scala vô danh (42 dòng) mà tôi sẽ đăng trong một vài ngày.

Đây là code-golf - câu trả lời ngắn nhất thắng.


Là phân chia được đảm bảo là chính xác?
Peter Taylor

@Peter Có. Mỗi bước sẽ dẫn đến một số nguyên.
Gareth

Nhưng nếu bước là "/ 3", có đảm bảo rằng phần còn lại sẽ luôn là 0 không?
Peter Taylor

@Peter Có, phần còn lại sẽ luôn là 0.
Gareth

Câu trả lời:


12

Golfscript, 203 138 ký tự

~]0{).2$.);[\(;]zip\/zip{.{~-}%.&({-}+\{;{.0={.~\%{.~%{;0}{~/{/}+}if}{~\/{*}+}if}{~!{;}*}if}%.&(\{;;0}/}{\;}if}%.{!}%1?)!{0}*}do\@)\,@%@=~

Điều này sử dụng nhiều hơn nhiều ifso với một chương trình Golfscript tiêu chuẩn và hoạt động của nó khá khó hiểu, vì vậy đây là một phiên bản được nhận xét (nhưng không bị sai lệch ngoài việc thêm phiên bản khoảng trắng và bình luận):

~]0
# Loop over guesses L for the length of the sequence
{
    # [x0 ... xN] L-1
    ).
    # [x0 ... xN] L L
    2$.);[\(;]zip
    # [x0 ... xN] L L [[x0 x1][x1 x2]...[x{N-1} xN]]
    \/zip
    # [x0 ... xN] L [[[x0 x1][xL x{L+1}]...][[x1 x2][x{L+1} x{L+2}]...]...]
    {
        # [x0 ... xN] L [[xi x{i+1}][x{i+L} x{i+L+1}]...]
        # Is there an operation which takes the first element of each pair to the second?
        # Copy the pairs, work out each difference, and remove duplicates
        .{~-}%.&
        # Turn the first difference into an operation
        ({-}+\
        # If there was more than one unique difference, look for a multiplication
        {
            ;
            # [x0 ... xN] L [[xi x{i+1}][x{i+L} x{i+L+1}]...]
            # Do something similar, but working out multiplicative factors
            # Note that if we have [0 0] it could be multiplication by anything, so we remove it.
            # However, they can't all be [0 0] or we'd have only one unique difference
            {
                # [0     0   ] =>
                # [0     _   ] => 0     # a "false" value, because it can't possibly be multiplication
                # [a     a.b'] => {b'*}
                # [a'.b  b   ] => {a'/}
                # [_     _   ] => 0     # ditto
                # This is the obvious place to look for further improvements
                .0={.~\%{.~%{;0}{~/{/}+}if}{~\/{*}+}if}{~!{;}*}if
            }%.&
            # If we have one unique multiplication, even if it's false, keep it.
            # Otherwise discard them and replace them with false.
            (\{;;0}/
        }
        # There was only one unique difference. Discard the pairs
        {\;}if
        # operation - one of 0, {d+}, {m*}, {M/}
    }%
    # [x0 ... xN] L [op0 ... op{L-1}]
    # Is any of the operations false, indicating that we couldn't find a suitable operation?
    .{!}%1?
    # [x0 ... xN] L [op0 ... op{L-1}] idxFalse
    # If idxFalse is -1 then all the ops are ok, and we put a false to exit the loop
    # Otherwise one op failed, so we leave the array of ops, which is non-false, to be popped by the do.
    )!{0}*
}do
# [x0 ... xN] L [op0 ... op{L-1}]
\@)\,@%@=~
# op{(len(Xs)-1)%L} (Xs[-1])

Trình ban đầu của tôi là sau 88 ký tự:

~]:x;2.{;).(2base(;{[{--}{@*\.!+/}]=}%[x.(;2$]zip\,<{~++}%x,.@[*x\]zip<{~~}%)\x(;=!}do\;

Tuy nhiên, điều này cố gắng tính toán các hoạt động từ lần xuất hiện đầu tiên của mỗi lần, vì vậy nếu hoạt động là phép nhân hoặc phép chia và đối số thì vòng đầu tiên là 0, nó sẽ bị hỏng.


1
Cảm ơn bạn rất nhiều vì đã đăng một lời giải thích! Tôi đã tìm kiếm các chương trình Golfscript mổ xẻ để tôi có thể cố gắng hiểu ý nghĩa của chúng hơn.
Migimaru

6

Haskell, 276 261 259 257 243 ký tự

Đây là giải pháp không hiệu quả của tôi. Nó hoạt động trên các số nguyên không giới hạn (và giới hạn). Giải pháp này xảy ra để hoạt động chính xác với phân chia không chính xác (ví dụ 5 / 2 = 2:).

import Control.Monad
main=interact$show.n.q read.words
f=flip
q=map
_%0=0
x%y=div x y
s b=[1..]>>=q cycle.(f replicateM$[(+),(*),(%)]>>=f q[-b..b].f)
m l x s=[y!!l|y<-[scanl(f($))(x!!0)s],x==take l y]
n x=(s(maximum$q abs x)>>=m(length x)x)!!0

Cách thức hoạt động: Tôi tạo mọi chuỗi hoạt động có thể (có thể). Sau đó, tôi kiểm tra chuỗi số đầu vào để xem chuỗi được tạo sẽ tạo đầu vào. Nếu có, trả về số tiếp theo trong chuỗi. Mã sẽ luôn trả về một câu trả lời bắt nguồn từ một chuỗi các hoạt động ngắn nhất. Điều này xảy ra bởi vì danh sách các chuỗi hoạt động được tạo theo thứ tự đó. Đó là tùy ý (nhưng nhất quán) về việc quyết định giữa các mối quan hệ. Ví dụ mã trả về 6hoặc 8cho chuỗi 2 4.

Ung dung:

import Control.Monad

main :: IO ()
main = print . next . map read . words =<< getLine

opSequences :: Integral a => a -> [[a -> a]]
opSequences bound = [1 ..] >>= map cycle . (`replicateM` (ops >>= (`map` args) . flip))
  where
    ops = [(+), (*), \x y -> if y == 0 then 0 else div x y]
    args = [-bound .. bound]

match :: (MonadPlus m, Integral a) => [a] -> [a -> a] -> m a
match ns opSeq = guard (ns == take len ms) >> return (ms !! len)
  where
    n0 = ns !! 0
    len = length ns
    ms = scanl (flip ($)) n0 opSeq

next :: Integral a => [a] -> a
next ns = (opSequences bound >>= match ns) !! 0
  where
    bound = maximum $ map abs ns

Ý tưởng tốt đẹp cho cách xử lý phân chia không chính xác.
Peter Taylor

Đó là một tác dụng phụ tình cờ. Tìm kiếm một giải pháp chỉ là ý tưởng ban đầu của tôi về cách giải quyết vấn đề này, đối với tôi, nó cảm thấy giống như một nhiệm vụ đơn giản hơn là tính toán câu trả lời.
Thomas Eding

Control.Monad -> Monadthể không? Và làm thế nào vềinteract$show.n.q read.words
FUZxxl

6

Python, 333 366 ... 315 303 278 269 261 246 chars

n=map(float,raw_input().split())
y=len(n)-1
l=1
def O(f):
 p,q=n[f:y:l],n[f+1::l]
 for a,b in zip(p,q):
    for x in((b-a).__add__,(b/(a or 1)).__mul__):
     if map(x,p)==q:return x
while 1:
 if all(map(O,range(l))):print int(O(y%l)(n[y]));break
 l+=1

Tạo hoạt động với cặp số đầu tiên và kiểm tra nó trên các cặp khác. Lưu trữ tất cả các hoạt động và nếu tất cả chúng thành công thì áp dụng thao tác phù hợp trong danh sách phần tử cuối cùng.

Đã chỉnh sửa: vượt qua bài kiểm tra xấu xa :-) Bây giờ hãy tìm kiếm hoạt động trên tất cả các vị trí.


Đẹp. Vượt qua tất cả các bài kiểm tra của tôi, nhưng không phải bài kiểm tra đặc biệt xấu xa của Peter Taylor:0 0 1 2 3 6 7 14
Gareth

0 0 0 0 1 0 0 0 0 1không đầu ra 0.
Thomas Eding

@trinithis Đầu vào đó không phù hợp với thông số kỹ thuật. Trình tự các hoạt động phải lặp lại hoàn toàn ít nhất một lần.
Gareth

1
Oooh, đây là một cải tiến thú vị: lambda x:x+b-a-> (b-a).__add__. Thật tệ, đó chỉ là một nhân vật, tôi học được rất nhiều về con trăn bằng cách làm những điều này.
Cluless

1
Làm lngầm toàn cầu tiết kiệm rất nhiều: pastie.org/2416407
Clueless

4

Python, 309 305 295 279 ký tự

Xử lý tất cả các trường hợp thử nghiệm ban đầu, cũng như trường hợp sởn gai ốc của Peter Taylor 0 0 1 2 3 6 7 14:

l=map(int,raw_input().split())
i=v=0
while v<1:
 v=i=i+1
 for j in range(i):
    p=zip(l[j::i],l[j+1::i])
    d,r=set(q[1]-q[0]for q in p),set(q[1]*1./(q[0]or 1)for q in p if any(q))
    m,n=len(d)<2,len(r)<2
    v*=m+n
    if(len(l)-1)%i==j:s=l[-1]+d.pop()if m else int(l[-1]*r.pop())
print s

Ungolfed, với đầu ra gỡ lỗi (rất hữu ích trong việc xác minh tính chính xác):

nums = map(int,raw_input().split())
result = None

for i in range(1,len(nums)/2+1):
    print "-- %s --" % i
    valid = 1
    for j in range(i):
        pairs = zip(nums[j::i], nums[j+1::i])
        print pairs

        diffs = [pair[1] - pair[0] for pair in pairs]
        # this is the tough bit: (3, 6) -> 2, (0, 5) -> 5, (5, 0) -> 0, (0, 0) ignored
        ratios = [float(pair[1])/(pair[0] or 1) for pair in pairs if pair[0] != 0 or pair[1] != 0]

        if len(set(diffs))==1:
            print "  can be diff", diffs[0]
            if (len(nums) - 1) % i == j:
                result = nums[-1] + diffs.pop()
        elif len(set(ratios))==1:
            print "  can be ratio", ratios[0]
            if (len(nums) - 1) % i == j:
                result = int(nums[-1]*ratios.pop())
        else:
            print "** invalid period **"
            valid=0
    if valid and result is not None:
        break

print result

Sử dụng:

echo 0 0 1 2 3 6 7 14 | python whatcomesnext.py

Tôi đã nâng cấp, mặc dù nói đúng, đầu vào phải thông qua stdin chứ không phải đối số lệnh.
Gareth

Điều đó thực sự cho phép tôi rút ngắn chương trình bằng bốn ký tự :)
Cluless

Rất ít ký tự, i = v = 0 và trong khi v == 0:
Ante

@Ante cảm ơn, tôi nghĩ bạn không thể làm điều đó với python vì bài tập không phải là một biểu thức, nhưng đó là một miếng ngon hữu ích cho việc chơi golf. Các tab nghĩa đen như thụt cấp độ thứ hai cũng giúp.
Cluless

Tôi không phải là Pythoner, nhưng dường như bạn đang sử dụng booleans làm số nguyên trong một số biểu thức và chưa thể sử dụng số nguyên v làm boolean trong bài kiểm tra while. Có đúng không? Nếu vậy, chắc chắn v<1làm việc như một người bảo vệ.
Peter Taylor

2

Ruby 1.9 (437) (521) (447) (477)

Hoạt động cho tất cả các trường hợp thử nghiệm, bao gồm cả trường hợp "xấu xa". Tôi sẽ đánh gôn nó muộn hơn.

EDIT: Tôi nhận ra có một trường hợp khác mà tôi đã không xử lý đúng cách - khi việc tiếp tục cần sử dụng thao tác "bí ẩn". Chuỗi 2 0 0 -2 -4 -6ban đầu được trả về 0 thay vì -12. Bây giờ tôi đã sửa nó.

EDIT: Đã sửa một vài trường hợp cạnh khác và cắt mã xuống còn 447.

EDIT: Ugh. Phải thêm một số mã để xử lý các chuỗi "xấu xa" khác như0 0 0 6 18 6 12

def v(c,q);t=*q[0];q.size.times{|i|f=c[z=i%k=c.size]
f=c[z]=(g=q[z+k])==0??_:((h=q[z+k+1])%g==0?"*(#{h/g})":"/(#{g/h})")if f==?_
t<<=f==?_?(a=q[i];b=q[i+1].nil?? 0:q[i+1];(a==0&&b==0)||(a!=0&&(b%a==0||a%b==0))?b:0):eval(t.last.to_s+f)}
*r,s=t
(p s;exit)if q==r
end
s=gets.split.map &:to_i
n=[[]]
((s.size-1)/2).times{|i|a,b=s[i,2]
j=["+(#{b-a})"]
j<<=?_ if a==0&&b==0
j<<="*#{b/a}"if a!=0&&b%a==0
j<<="/#{a/b}"if a*b!=0&&a%b==0
n=n.product(j).map(&:flatten)
n.map{|m|v(m*1,s)}}

1

Scala

Đây là giải pháp tôi đã đưa ra:

object Z extends App{var i=readLine.split(" ").map(_.toInt)
var s=i.size
var(o,v,f)=(new Array[Int](s),new Array[Double](s),1)
def d(p:Int,j:Array[Int]):Unit={if(p<=s/2){def t(){var a=new Array[Int](s+1)
a(0)=i(0)
for(l<-0 to s-1){o(l%(p+1))match{case 0=>a(l+1)=a(l)+v(l%(p+1)).toInt
case _=>a(l+1)=(a(l).toDouble*v(l%(p+1))).toInt}}
if(a.init.deep==i.deep&&f>0){f^=f
println(a.last)}}
o(p)=0 
v(p)=j(1)-j(0)
t
d(p+1,j.tail)
o(p)=1
v(p)=j(1).toDouble/j(0).toDouble
t
d(p+1,j.tail)}}
d(0,i)
i=i.tail
d(0,i)}

Ung dung:

object Sequence extends App
{
    var input=readLine.split(" ").map(_.toInt)
    var s=input.size
    var (ops,vals,flag)=(new Array[Int](s),new Array[Double](s),1)
    def doSeq(place:Int,ints:Array[Int]):Unit=
    {
        if(place<=s/2) 
        {
            def trysolution()
            {
                var a=new Array[Int](s+1)
                a(0)=input(0)
                for(loop<-0 to s-1)
                {
                    ops(loop%(place+1))match
                    {
                        case 0=>a(loop+1)=a(loop)+vals(loop%(place+1)).toInt
                        case _=>a(loop+1)=(a(loop).toDouble*vals(loop%(place+1))).toInt
                    }
                }
                if(a.init.deep==input.deep&&flag>0)
                {
                    flag^=flag
                    println(a.last)
                }
            }
            ops(place)=0
            vals(place)=ints(1)-ints(0)
            trysolution
            doSeq(place+1,ints.tail)
            ops(place)=1
            vals(place)=ints(1).toDouble/ints(0).toDouble
            trysolution
            doSeq(place+1,ints.tail)
        }
    }
    doSeq(0,input)
    input=input.tail
    doSeq(0,input)
}

Làm thế nào để tôi gọi nó? echo "0 0 1 2 3 6 7 14" | scala Sequencegiữ cho màn hình màu đen.
người dùng không xác định

@user không xác định scala Sequencevà sau đó nhập chuỗi và nhấn enter.
Gareth

Ah, bạn đã viết trong phần bình luận câu hỏi, rằng bạn không giải được câu hỏi cụ thể này - nó hoạt động với echo - pipe như trên cho các câu hỏi có thể giải được.
người dùng không xác định

1

Scala 936

type O=Option[(Char,Int)]
type Q=(O,O)
type L=List[Q]
val N=None
def t(a:Int,b:Int):Q=if(a>b)(Some('-',a-b),(if(b!=0&&b*(a/b)==a)Some('/',a/b)else N))else
(Some('+',b-a),(if(a!=0&&a*(b/a)==b)Some('*',b/a)else N))
def w(a:Q,b:Q)=if(a._1==b._1&&a._2==b._2)a else
if(a._1==b._1)(a._1,N)else
if(a._2==b._2)(N,a._2)else(N,N)
def n(l:L):Q=l match{case Nil=>(N,N)
case x::Nil=>x
case x::y::Nil=>w(x,y)
case x::y::xs=>n(w(x,y)::xs)} 
def z(l:L,w:Int)=for(d<-1 to w)yield
n(l.drop(d-1).sliding(1,w).flatten.toList)
def h(s:L):Boolean=s.isEmpty||(s(0)!=(N,N))&& h(s.tail)
def j(s:L,i:Int=1):Int=if(h(z(s,i).toList))i else j(s,i+1)
def k(b:Int,o:Char,p:Int)=o match{case'+'=>b+p
case'-'=>b-p
case'*'=>b*p
case _=>b/p}
val e=getLine 
val i=e.split(" ").map(_.toInt).toList
val s=i.sliding(2,1).toList.map(l=>t(l(0),l(1)))
val H=n(s.drop(s.size%j(s)).sliding(1,j(s)).flatten.toList)
val c=H._1.getOrElse(H._2.get)
println (k(i(i.size-1),c._1,c._2))

vô dụng:

type O = Option[(Char, Int)]

def stepalize (a: Int, b: Int): (O, O) = (a > b) match {
   case true => (Some('-', a-b), (if (b!=0 && b * (a/b) == a) Some ('/', a/b) else None)) 
   case false=> (Some('+', b-a), (if (a!=0 && a * (b/a) == b) Some ('*', b/a) else None)) }

def same (a: (O, O), b: (O, O)) = {
  if (a._1 == b._1 && a._2 == b._2) a else
  if (a._1 == b._1) (a._1, None) else 
  if (a._2 == b._2) (None, a._2) else 
  (None, None)}

def intersection (lc: List[(O, O)]): (O, O) = lc match {
  case Nil => (None, None)
  case x :: Nil => x
  case x :: y :: Nil => same (x, y)
  case x :: y :: xs  => intersection (same (x, y) :: xs)} 

def seriallen (lc: List[(O, O)], w: Int= 1) =
  for (d <- 1 to w) yield 
    intersection (lc.drop (d-1).sliding (1, w).flatten.toList)

def hit (s: List[(O, O)]) : Boolean = s match {
  case Nil => true 
  case x :: xs => (x != (None, None)) && hit (xs)}

def idxHit (s: List[(O, O)], idx: Int = 1) : Int =
  if (hit (seriallen (s, idx).toList)) idx else 
    idxHit (s, idx+1)

def calc (base: Int, op: Char, param: Int) = op match {
  case '+' => base + param
  case '-' => base - param
  case '*' => base * param
  case _   => base / param}

def getOp (e: String) = {
  val i = e.split (" ").map (_.toInt).toList
  val s = i.sliding (2, 1).toList.map (l => stepalize (l(0), l(1)))
  val w = idxHit (s)
  val hit = intersection (s.drop (s.size % w).sliding (1, w).flatten.toList)
  val ci = hit._1.getOrElse (hit._2.get)
  val base = i(i.size - 1)
  println ("i: " + i + " w: " + w + " ci:" + ci + " " + calc (base, ci._1, ci._2))
}

val a="1 3 5 7 9 11"
val b="1 3 2 4 3 5 4 6 5 7 6"
val c="2 6 7 3 9 10 6 18 19 15 45 46"
val d="1024 512 256 128 64 32 16"
val e="1 3 9 8 24 72 71 213 639"
val f="1 2 3 4 5 2 3 4 5 6 3 4 5 6 7"
val g="1 2 4 1 3 9 5 8 32 27 28 56 53 55 165 161 164 656 651 652 1304"
val h="0 0 1 2 3 6 7 14"
val i="0 0 0 0 1 0 0 0 0 1 0"

List (a, b, c, d, e, f, g, h, i).map (getOp)

Thất bại thảm hại với Peter Taylor h, nhưng tôi không thấy khả năng chữa lành chương trình trong một khoảng thời gian hợp lý.


Nó sẽ giúp thu nhỏ nó nếu bạn đối xử -như một trường hợp đặc biệt +/như một trường hợp đặc biệt *? Cách vượt qua đầu vào của Peter Taylor (và tương tự) là cắt số đầu tiên trong chuỗi và thử lại. Tôi chưa có thời gian để xem chương trình của bạn hoạt động như thế nào để biết liệu điều đó có giúp ích gì cho bạn không.
Gareth

Tôi đoán nó sẽ giúp ích, nhưng chỉ trong trường hợp đặc biệt đó. Một chuỗi có chứa phép nhân null sau này, giống như -1, 0, 0, 1, 2, 3, 6, 7, 14sẽ cần một sự chữa lành khác.
người dùng không xác định
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.