2
\$\begingroup\$

Write a program, that takes 5 numbers as input and outputs the next number in the pattern.

Heres a text file with 1835 test patterns, containing 6 numbers separated by commas each line. Using the first 5 numbers calculate the 6th number and then check if it matches. You must get all the test cases correct.

There are 3 types of patterns:

  1. xn = xn-1+k

  2. xn = xn-1*k

  3. xn = xn-1^2

The first x value and k were chosen randomly between a set range to create the pattern sample file.

This is code-golf, lowest number of bytes to get all of the test cases correct wins.

\$\endgroup\$
  • 3
    \$\begingroup\$ It seems fairly easy to get 100%. Is there a tiebreak? \$\endgroup\$ – xnor Sep 18 '14 at 5:57
  • \$\begingroup\$ The tiebreaker should be the length of the code because any solution can easily be O(n) time, i'll edit the question. Well this is just a duplicate of the other question then, should it be closed? \$\endgroup\$ – rodolphito Sep 18 '14 at 6:43
  • \$\begingroup\$ In that case, why don't you make it code golf and require getting all the test cases right? \$\endgroup\$ – xnor Sep 18 '14 at 6:46
  • 1
    \$\begingroup\$ Its pretty disappointing there are no trick rows; contestants are getting a perfect score by checking just the first three ints, and there's no divide-by-zeros being thrown either. \$\endgroup\$ – Will Sep 18 '14 at 7:53
  • 2
    \$\begingroup\$ -1 for doing big changes in the scoring system. Please use the sandbox the next time \$\endgroup\$ – John Dvorak Sep 18 '14 at 8:39
4
\$\begingroup\$

Python 2: 55 bytes

f=lambda a,b,c,d,e:e+c-d*2and e*e/d**(d*d==e*c)or e*2-d

We check for the three cases as follows:

  1. Check for arithmetic sequence: If e+c==d+d, output e+e-d
  2. Check for geometric sequence: If e*c==d*d, output e*e/d
  3. Otherwise, squared sequence: Output e*e.

Case 3 is used as the else-case to avoid the more-lengthy checking for successive squaring.

Case 1 is checked first, with Boolean short-circuiting to avoid checking Case 2 after a success, as this causes an error when d=0. There's a test case of all zeroes, so we can't cheat this by picking another position in place of d.

Afterwards, we can treat both Cases 2 and 3, since there's no risk of a divide-by-0 error. Noting that the choices are similar (e*e vs e*e/d), we combine them with an arithmetic expression by dividing by either d**1 for Case 3 or d**0 for Case 2. Although this division produces an integer value, we must use Python 2 (or //) to avoid float errors that case the largest-output test case to fail.

Thanks to @Will for inspiration on the code structure and a very-helpful test framework.

\$\endgroup\$
  • \$\begingroup\$ Still, like the multiply instead of and :) \$\endgroup\$ – Will Sep 21 '14 at 9:39
3
\$\begingroup\$

Python all right, 72 74 75 chars

p=lambda i,j,k,l,m:j-i!=k-j and(k==j*j==j*i*i and m*m or m*l/k)or m+j-i

Thx to xnor for showing me the if/else to and/or trick and golfing off a char :)

Thx to flornquake for fixing the k==j*j==j*i*i and saving another two chars :)

Actually, it gets one wrong... but that's a bug in the test patterns which was acknowledged yesterday but still not fixed.

Testing code, hopefully useful for all competitors to test with:

def check(func,title):
    right = 0
    print "===", title, "==="
    for i,test in enumerate(open('patterns.txt')):
        test = map(int,test.split(','))
        try:
            got, expected = func(*test[:5]), test[5]
        except Exception as e:
            got = e
        if got != expected:
            print "ERROR on line %d: %s != %d" % (i, got, expected)
            print " test :", ", ".join(map(str,test))
            plus = multi = cube = str(test[0])
            for i in range(1, 6):
                plus += ", %d" % (test[i-1]+(test[1]-test[0]))
                multi += ", %s" % ((test[i-1]*(test[1]/test[0])) if test[0] else "DivZero")
                cube += ", %d" % (test[i-1]**2)
            print " as + :", plus
            print " as * :", multi
            print " as ^2:", cube 
        else:
            right += 1
    print right, "out of", i+1, "right!"

says:

ERROR on line 19: 23283064365386962890625 != 3273344365508751233
 test : 5, 25, 625, 390625, 152587890625, 3273344365508751233
 as + : 5, 25, 45, 645, 390645, 152587890645
 as * : 5, 25, 125, 3125, 1953125, 762939453125
 as ^2: 5, 25, 625, 390625, 152587890625, 23283064365386962890625
1834 out of 1835 right!
\$\endgroup\$
  • \$\begingroup\$ You can usually save chars from the if/else ternany operator using the and/or trick: codegolf.stackexchange.com/a/57/20260 \$\endgroup\$ – xnor Sep 19 '14 at 8:33
  • \$\begingroup\$ I had deleted my suggestion of k==j*j==i**4 on realizing it fails for 1, -1, 1, -1, 1, -1, but it turns out you can dodge it by using j,k,l instead, which changes the parity. I assume it's allowed to take advantage of a coincidental hole in the test cases? \$\endgroup\$ – xnor Sep 19 '14 at 8:56
  • \$\begingroup\$ @xnor thx for the encouragement and leads :) I don't really want to take advantage of holes in the test cases. And the I didn't know that neat and/or trick! But its not applicable for this particular problem because the correct prediction may be falsy, e.g. -10, -8, -6, -4, -2, 0. Still neat to learn. \$\endgroup\$ – Will Sep 19 '14 at 8:59
  • \$\begingroup\$ Hmm, I think and/or should just work, independent of the truthiness of the output. Let's try to fix it. Can you check that you converted a if b else c to b and a or c? And also that the two of it are nested right and perhaps parenthesized to parse right? If it still doesn't work, could you please tell me what you have. \$\endgroup\$ – xnor Sep 19 '14 at 9:04
  • \$\begingroup\$ @xnor q=lambda i,j,k,l,m:j-i==k-j and m+j-i or(j==i*i)&(k==j*j)and m*m or m*l/k is how I wrote it. \$\endgroup\$ – Will Sep 19 '14 at 9:05
2
\$\begingroup\$

C# - 1835

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace pattern
{
    class Program
    {
         static void Main(string[] args)
         {
            string[] lines = File.ReadAllLines("in.txt");
            int matches = 0;
            for(int i = 0; i < lines.Length; i++)
            {   
                long[] numbers = lines[i].Split(',').Select(a=>long.Parse(a)).ToArray();

                long nextnum = 0;
                if(numbers[1]-numbers[0]==numbers[2]-numbers[1])
                nextnum = numbers[numbers.Length-2]+(numbers[1]-numbers[0]);
            else if(numbers[1]/numbers[0]==numbers[2]/numbers[1])
                nextnum = numbers[numbers.Length-2]*(numbers[1]/numbers[0]);
            else if(numbers[1] == numbers[0]*numbers[0])
                nextnum = numbers[numbers.Length-2]*numbers[numbers.Length-2];
            if(nextnum == numbers[numbers.Length-1])
                matches++;
        }
        Console.WriteLine(matches + " matches found!");
        Console.ReadLine();
    }
}
}

This is obviously not golfed at all, but it finds all numbers eventually. It just prints how many matches it found, but you could potentially display all found numbers, only non-matches, etc...

(This is conceptually very similar to Beta Decay's answer, just a little bit more complicated)

\$\endgroup\$
  • \$\begingroup\$ I love C#, it is like a mixture of everything, it has lambdas, anonymous delegates, LINQ, and a bunch of other features haha, not exactly fit for golfing though :P \$\endgroup\$ – rodolphito Sep 18 '14 at 6:47
  • \$\begingroup\$ Yeah, C# is great for some purposes. Well, like I said, I didn't golf this a whole lot :P \$\endgroup\$ – Christoph Böhmwalder Sep 18 '14 at 7:37
2
\$\begingroup\$

Python 3 -1833

Length 198 chars

Now updated to conform to the rules.

m=0
for i in open('s'):
 if','in i:
  i,j,k,l=list(map(int,i.split(',')[2:]))
  if j-i==k-j:
   if k+(j-i)==l:m+=1
  elif j/i==k/j:
   if k*(j/i)==l:m+=1
  elif i**2==j:
   if k**2==l:m+=1
print(m)
\$\endgroup\$
  • \$\begingroup\$ You can golf this a lot (the rules are changing under us and code size is now important) e.g. for i in open('s.txt'): and unpacking the first three ints in the split etc. \$\endgroup\$ – Will Sep 18 '14 at 6:56
  • 1
    \$\begingroup\$ here's a 112 byte version, but I miss tricks: gist.github.com/williame/f8ae068ff7e658cde28f \$\endgroup\$ – Will Sep 18 '14 at 7:05
  • 1
    \$\begingroup\$ I know this has been accepted by the poster, so must meet their criteria of correctness, but it seems to be overlooking the requirement Using the first 5 numbers calculate the 6th number and then check if it matches? \$\endgroup\$ – Will Sep 18 '14 at 8:11
  • 4
    \$\begingroup\$ i**2 is longer than i*i. \$\endgroup\$ – Rainbolt Sep 18 '14 at 15:19
  • 4
    \$\begingroup\$ Python can read from files without a .txt extension (I just tested this). The name of the file was not specified in the problem, so you should shave off four characters by naming it a single letter. for i in open('s'):, assuming the file was named "s". \$\endgroup\$ – Rainbolt Sep 18 '14 at 15:24
1
\$\begingroup\$

TI-BASIC, 120 117 136

Prompts for input and returns the output.

Input L1:0:If not(L1(5:Stop
If L1(5)-L1(4)=L1(4)-L1(3:L1(5)+(L1(5)-L1(4
If L1(5)/L1(4)=L1(4)/L1(3:L1(5)(L1(5)/L1(4
If L1(4)²=L1(5:L1(5)²

Edit: Fixed divide by zero error.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.