9
\$\begingroup\$

This is based on this challenge and Geobits's/CarpetPython's idea to improve it:

Keep your distance!

For this challenge, the distance between two numbers is measured on a loop, so, for example, the distance between 0 and 999 is 1. This should prevent strategies like always picking the lowest or highest number from winning almost every time. The only other change is that the lowest number that can be chosen is now 0 instead of 1.

I'll summarize it here:

  • Write a function in Java, Python, or Ruby that takes three arguments:
    • the number of rounds played so far
    • the number of players
    • the numbers picked in the previous rounds, as an array of space-separated strings
  • It should return an integer from 0 to 999, inclusive
  • The score for a program each round is the sum of the square roots of the distances to the numbers each other program picked
  • The program with the highest score after 100 rounds wins.
  • One answer per person

The control program is here:

https://github.com/KSFTmh/src/

Leaderboard

NumberOne, by TheBestOne, is winning.

  • NumberOne - 9700
  • NumberOnePlusFourNineNine - 9623
  • AncientHistorian - 9425
  • FindCampers - 9259
  • WowThisGameIsSoDeep - 9069
  • Sampler - 9014
  • SabotageCampers - 8545

Apparently, my camper sabotage...er(?) doesn't work very well.

Here are the full results: https://github.com/KSFTmh/src/blob/master/results-3

I think this is different enough to not be a duplicate.

By the way, this is my first time asking a question on Stack Exchange, so let me know if I'm doing something wrong.

\$\endgroup\$
29
  • 4
    \$\begingroup\$ Do we really want a question this similar ? \$\endgroup\$
    – Optimizer
    Commented Jan 31, 2015 at 20:13
  • 5
    \$\begingroup\$ @Optimizer A few people in the comments seemed to think this was a good idea. Answers from the original will work very differently here, so I don't think it's a duplicate. \$\endgroup\$
    – KSFT
    Commented Jan 31, 2015 at 20:14
  • 1
    \$\begingroup\$ The credit for suggesting the challenge should go to @Geobits. I just agreed with him. \$\endgroup\$ Commented Feb 1, 2015 at 2:31
  • 1
    \$\begingroup\$ Mmm. It seems that a constant number wins again. I am curious as to why that is. Could we see the 600 output numbers in the question, or on github or pastebin? I suspect some of our predictors have bugs. Possibly mine :-( \$\endgroup\$ Commented Feb 2, 2015 at 3:07
  • 1
    \$\begingroup\$ @CarpetPython A simple change would be to compute the distance between the points from last around in addition to the points from this round. \$\endgroup\$ Commented Feb 3, 2015 at 3:57

8 Answers 8

3
\$\begingroup\$

Python 2, Sampler

This entry is based on the same code for Keep your distance, Sampler entry. I hope it will do better here where the 1 and 999 advantages do not exist.

Out of a list of places, choose the one that is farthest away from recently used numbers, ignoring the previous turn (because other entries may predict based on just the previous turn).

def choose(turn, players, history):
    sample = map(int, (' '.join( history[-5:-1] )).split())
    def distance(x):
        return sum(min(1000-abs(x-y), abs(x-y))**0.5 for y in sample)
    score, place = max((distance(x), x) for x in range(1000))
    return place
\$\endgroup\$
1
  • \$\begingroup\$ It looks like this one's winning, but that might be because I'm not compiling the controller right and the others are all crashing. \$\endgroup\$
    – KSFT
    Commented Feb 1, 2015 at 18:29
2
\$\begingroup\$

Number OnePlusFourNineNine, Java

public static int choose(int round, int players, String[] args) {
    return 500;
}

The logic is really simple. Unless someone finds a real algorithm which takes previous scores into consideration, this answer is fairly optimized.

Now that we count the distance in a circle, the maximum distance of any two points can be 500. Now if all entries were generating random numbers (or pseudo random based on some algorithm), this answer would not have been in any advantage at all. But there is at least 1 entry which produces a constant answer which an almost maximum distance. The makes the score come in favor of 500 as there is a fixed source of maximum distance possible in each round :)

\$\endgroup\$
2
  • \$\begingroup\$ You optimized my answer. ;) \$\endgroup\$ Commented Feb 1, 2015 at 22:34
  • \$\begingroup\$ @TheBestOne haha \$\endgroup\$
    – Optimizer
    Commented Feb 2, 2015 at 5:00
2
\$\begingroup\$

AncientHistorian - Python

It is the same algorithm from the previous one, except when calculating the potential scores it uses the circular distance. Since I'm losing horribly and can't get the controller to compile, I'm just trying a new strategy, where I use the worst from the previous rounds.

def choose(round, players, scores):
    calc = lambda n, scores: sum([min(abs(int(i)-n), 1000-max(int(i),n)+min(int(i),n))**.5 for i in scores.split(' ')])
    return min(range(1000), key=lambda n: sum([calc(n, j) for j in scores[1:]])) if round>1 else 250
\$\endgroup\$
2
  • \$\begingroup\$ This doesn't work. i is an element of scores.split(' '), meaning it's a string, not an int. \$\endgroup\$
    – KSFT
    Commented Feb 1, 2015 at 18:25
  • \$\begingroup\$ @KSFT oh shoot, I really should have tested, updating. \$\endgroup\$
    – Maltysen
    Commented Feb 1, 2015 at 23:10
2
\$\begingroup\$

SabotageCampers - Python

def choose(rounds, players, previous):
    if rounds<3:
        return 1
    prevchoices=[int(i) for i in " ".join(previous[-5:]).split(" ")]
    remove=[]
    for i in prevchoices:
        if prevchoices.count(i)<3:
            remove.append(i)
    campers=[i for i in prevchoices if i not in remove]
    return random.choice(campers)

The campers are still winning. Let me know if you have any suggestions for this.

\$\endgroup\$
2
\$\begingroup\$

FindCampers - Python 2

Find all the campers from the last 10 rounds and stay away from them. I'm hoping that predictors will run from me. I will now ignore my old choices.

def choose(rounds, players, previous):
    from collections import Counter

    def distance(x, y):
        return min(1000 - abs(x-y), abs(x-y))

    pastRounds = list(map(lambda x: Counter(map(int, x.split())), previous))
    me = 751
    for (index, round) in enumerate(pastRounds):
        round.subtract((me,))
        pastRounds[index] = set(round.elements())
        campers = reduce(lambda x,y: x.intersection(y), pastRounds[max(1, index-9):index], pastRounds[max(0,index-10)])
        if campers:
            dist, me = max(min((distance(x, y), x) for y in campers) for x in range(1000))
        else:
            me = 751
    return me
\$\endgroup\$
8
  • \$\begingroup\$ Aww...I was hoping this would go towards the campers when I saw the name... \$\endgroup\$
    – KSFT
    Commented Feb 7, 2015 at 0:35
  • \$\begingroup\$ Lol. I could add an entry that will sabotage campers. \$\endgroup\$
    – Jmac
    Commented Feb 7, 2015 at 0:46
  • \$\begingroup\$ Unfortunately, I only allowed one entry per person. \$\endgroup\$
    – KSFT
    Commented Feb 7, 2015 at 0:47
  • \$\begingroup\$ I just posted an entry to sabotage campers myself. \$\endgroup\$
    – KSFT
    Commented Feb 8, 2015 at 16:02
  • \$\begingroup\$ Mine doesn't work because I didn't realize that previous results were sorted. How does yours detect campers? \$\endgroup\$
    – KSFT
    Commented Feb 8, 2015 at 16:21
1
\$\begingroup\$

Number One, Java

The first answer. Copied from my previous answer.

public static int choose(int round, int players, String[] args) {
    return 1;
}
\$\endgroup\$
1
  • \$\begingroup\$ Someone seems to have downvoted all of the answers. \$\endgroup\$
    – KSFT
    Commented Feb 1, 2015 at 4:18
1
\$\begingroup\$

WowThisGameIsSoDeep, Java

I have analyzed the game for 10 years on a 1 million-core cluster and found the optimal solution.

public static int choose(int round, int players,String[]spam) { return(int)(Math.random()*1e3); }
\$\endgroup\$
12
  • \$\begingroup\$ This ain't no code-golf \$\endgroup\$
    – Optimizer
    Commented Jan 31, 2015 at 21:38
  • 5
    \$\begingroup\$ That solution is not optimal. If you want a uniform distribution, you should use Random.nextInt(int). \$\endgroup\$ Commented Jan 31, 2015 at 22:20
  • \$\begingroup\$ This seems to always return 1. \$\endgroup\$
    – KSFT
    Commented Feb 2, 2015 at 4:11
  • \$\begingroup\$ @KSFT I tested it and got many different numbers. Maybe it's sabotage after all? \$\endgroup\$
    – feersum
    Commented Feb 2, 2015 at 4:16
  • 4
    \$\begingroup\$ Aha! I fixed it! I accidentally typed "WowThisGameIsSoDeep.py", and it was trying to run it as a Python file. \$\endgroup\$
    – KSFT
    Commented Feb 2, 2015 at 16:16
1
\$\begingroup\$

Circilinear Extrapolator, Ruby

def choose(round, players, previous_choices)
  previous_rounds = previous_choices.map{ |round| round.split.map(&:to_i) }
  optimal_past_choices = previous_rounds.map do |choices|
    (0..999).max_by { |i| choices.map{ |c| root_distance(i,c) }.inject(:+) }
  end
  if (last_round = optimal_past_choices.last)
    (last_round + average_delta(optimal_past_choices).round) % 1000
  else
    750
  end
end

def root_distance(i,j)
  dist = (i-j).abs
  dist = [dist, 1000 - dist].min
  dist ** 0.5
end

def directed_distance(i,j)
  dist = j - i
  if dist > 500
    dist - 1000
  elsif dist < -500
    dist + 1000
  else
    dist
  end
end

def average_delta(ary)
  ary.each_cons(2).map{ |x,y| directed_distance(x,y) }.inject(0,:+)/ary.count
end
\$\endgroup\$
9
  • \$\begingroup\$ This is giving this error: NoMethodError: undefined method `split' for #<Array:0x720f56e2> choose at CircilinearExtrapolator.rb:2 \$\endgroup\$
    – KSFT
    Commented Feb 1, 2015 at 21:56
  • \$\begingroup\$ Oh, is previous_choices an array of values like ["1 6 500","2 8 503"] ? \$\endgroup\$
    – histocrat
    Commented Feb 1, 2015 at 22:17
  • \$\begingroup\$ It is. Did you think it was something else? If not, I probably just messed something up running it. \$\endgroup\$
    – KSFT
    Commented Feb 1, 2015 at 22:18
  • \$\begingroup\$ I thought it was just a flat string, sorry. I'll edit. \$\endgroup\$
    – histocrat
    Commented Feb 1, 2015 at 22:18
  • \$\begingroup\$ Edited. Now everybody knows I posted something without testing it... \$\endgroup\$
    – histocrat
    Commented Feb 1, 2015 at 22:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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