Take It or Leave It II: Pertunjukan Game untuk Komputer


20

Ini adalah yang kedua dari serangkaian teka-teki yang akan saya posting setiap hari Senin di Midnight PST. Teka-teki pertama terletak di sini .

Konteks:

Seorang miliarder yang tertutup telah menciptakan acara permainan untuk menarik para programmer terbaik dan terpandai di dunia. Pada hari Senin di tengah malam, ia memilih satu orang dari kumpulan pelamar untuk menjadi kontestan minggu ini, dan memberi mereka permainan. Anda adalah kontestan yang beruntung minggu ini!

Game minggu ini:

Tuan rumah memberi Anda akses API ke tumpukan 10.000 amplop digital. Amplop ini diurutkan secara acak, dan di dalamnya berisi nilai dolar, antara $ 1 dan $ 10.000 (tidak ada dua amplop yang berisi nilai dolar yang sama).

Anda memiliki 4 perintah yang Anda inginkan:

  1. Baca (): Baca angka dolar dalam amplop di bagian atas tumpukan.

  2. Take (): Tambahkan angka dolar di dalam amplop ke dompet permainan Anda, dan keluarkan amplop dari tumpukan.

  3. Pass (): Lepaskan amplop di bagian atas tumpukan.

  4. Oracle (M): Mengembalikan nilai rata-rata amplop M berikutnya dalam tumpukan, tidak termasuk yang saat ini dapat Anda Baca ().

Aturan:

  1. Jika Anda menggunakan Pass () pada amplop, uang di dalamnya hilang selamanya.

  2. Jika Anda menggunakan Take () pada amplop yang berisi $ X, sejak saat itu, Anda tidak boleh menggunakan Take () pada amplop yang berisi <$ X. Ambil () pada salah satu amplop ini akan menambah $ 0 ke dompet Anda.

  3. Jika Anda menggunakan Oracle (M) pada giliran T, amplop T + 1 hingga rata-rata T + M akan dikembalikan. Oracle () dinonaktifkan hingga giliran T + M.

Tulis algoritma yang menyelesaikan permainan dengan jumlah uang maksimal.

Jika Anda menulis algoritme Anda dengan Python, jangan ragu untuk menggunakan pengontrol ini yang disediakan oleh @Maltysen: https://gist.github.com/livinginformation/70ae3f2a57ecba4387b5

Catatan 1: "Maksimal" dalam hal ini berarti nilai median di dompet Anda setelah N> = 1000 berjalan. Saya berharap, meskipun saya ingin terbukti salah, bahwa nilai median untuk algoritma yang diberikan akan konvergen ketika N meningkat hingga tak terbatas. Jangan ragu untuk mencoba memaksimalkan mean, tetapi saya merasa bahwa mean lebih mungkin terlempar oleh N kecil daripada mediannya.

Catatan 2: karena semua solusi untuk bagian sebelumnya dari teka-teki ini valid di sini, pengeposan ulang memiliki nilai yang kecil. Hanya peningkatan algoritmik dari teka-teki sebelumnya yang akan dipertimbangkan untuk bagian II.

Sunting: Kondisi hadiah telah dihapus, mengingat postingan ini tentang meta.


Wow, saya tidak percaya saya ketiduran: O
Beta Decay

@Beta Decay clock sudah berdetak! :)
LivingInformation

Apa arti kerutan itu? Anda dapat membangun oracle gratis Anda sendiri dengan hanya menyimpan penghitungan dari semua amplop yang sebelumnya dibaca. Apa yang salah?
Luis Mendo

1
@LuisMendo Dengan penghitungan Anda sendiri, Anda hanya bisa tahu arti semua nilai yang tersisa. Dengan oracle, Anda bisa mendapatkan nilai rata-rata selanjutnya M, di mana Anda bisa memilih M.
Reto Koradi

1
Karena semua solusi untuk tantangan Anda sebelumnya juga merupakan solusi yang valid untuk tantangan ini, dapatkah kami menganggapnya diserahkan secara implisit?
Reto Koradi

Jawaban:


9

Groovy $ 713337 $ 817829 $ 818227

Kode bootstrap:

class Instance {
    List values = new ArrayList(1..10000); {
        Collections.shuffle(values)
    }
    int i = 0
    int value = 0
    int max = 0
    int nextOracle = 0

    def pass() {
        if (i >= 10000)
            throw new NoSuchElementException()
        i++
    }

    def take() {
        if (i >= 10000)
            throw new NoSuchElementException()
        int v = values[i]
        if (v > max) {
            max = v
            value += v
        }
        i++
    }

    double oracle(int m) {
        if (m <= 0 || i < nextOracle || i + m >= 10000)
            throw new NoSuchElementException()

        nextOracle = i + m
        values.subList(i + 1, i + m + 1).stream().reduce { l, r -> r+l }.get() / m
    }

    int read() {
        if (i >= 10000)
            throw new NoSuchElementException()
        values[i]
    }
}

Algoritma

double square(double v) { v * v }
final double factor = Math.pow(1.5, 1.1)
int attempts = 5000
(1..attempts).stream().parallel().mapToLong {
    def puzzle = new Instance()

    int[] memory = 1..10000 // We will remember every envelope
    int memStart = 0

    while (memStart < 10000 - 3) {
        int value = puzzle.read()
        int i = Arrays.binarySearch(memory, memStart, 10000, value) - memStart
        if (i < 0) { // We can't use the money
            puzzle.pass()
            continue
        }
        if (i == 0) { // Of course we take the lowest
            puzzle.take()
            memStart++
            continue
        }
        int remaining = Arrays.stream(memory, i + 1 + memStart, 10000).sum() // Money we could win if taken
        int losing = Arrays.stream(memory, memStart, memStart + i).sum() // Money we cna't win if taken
        if (value > losing) { // If we pass, we lose money automatically
            puzzle.take()
            memStart += i + 1
        } else if ((losing - value * 16 / 7) * square(Math.log(i)) > remaining / factor) {
            System.arraycopy(memory, memStart, memory, ++memStart, i)
            puzzle.pass()
        } else {
            puzzle.take()
            memStart += i + 1
        }
    }

    // It's broken down to last three elements
    List values = Arrays.copyOfRange(memory, 10000 - 3, 10000)
    while (!values.contains(puzzle.read())) // Skip values we can't use
        puzzle.pass()
    int value1 = puzzle.read()
    int value2 = puzzle.oracle(1)
    if (value1 == values.max() && (
            values.contains(value2)
            ? (value1 * 2 < values.sum() && values.min() == value2)
            : (value1 < values.min() / 2 + (values - [value1]).max())
            )) {
        puzzle.pass()
    }

    // Finish it
    while (puzzle.i < puzzle.values.size()) {
        puzzle.take()
    }

    puzzle.value as Long
}.sum() / attempts // Sum runs and average

Saya membandingkan nilai yang tersisa dengan nilai yang mungkin. Skrip ini tidak cepat (membutuhkan 1 menit per 1000x simulasi) ... tetapi akan melakukan simulasi secara bersamaan.

Saya tidak tahu mengapa algoritme saya berfungsi, tetapi itu hanya coba-coba: menggabungkan operasi matematika dan memanipulasi konstanta. Saya menjalankannya 5000x untuk skor saat ini, dalam upaya untuk mengurangi fluktuasi skor (+/- $ 4000 tergantung pada jumlah iterasi).

Bahkan tanpa nubuat pada akhirnya, itu harus tetap (nyaris) mengalahkan solusi @ orlp untuk puzzle sebelumnya.


7

C # - $ 803,603 sekarang -> $ 804,760 (dengan oracle)

Kode Bootstrap

public static class ShuffleExtension
{
    private static Random rng = new Random();  

    public static void Shuffle<T>(this IList<T> list)  
    {  
        int n = list.Count;
        while (n > 1) {  
            n--;  
            int k = rng.Next(n + 1);  
            T value = list[k];  
            list[k] = list[n];  
            list[n] = value;  
        }  
    }
}

public class Puzzle
{
    public List<int> Values = new List<int>(10000);

    public Puzzle()
    {
        for ( int i = 1; i <= 10000; i++ )
        {
            Values.Add(i);
        }
        Values.Shuffle();
    }

    public int i = 0;
    public int value = 0;
    public int max = 0;
    public int nextOracle = 0;

    public void Pass() {
        if ( i >= Values.Count )
            throw new IndexOutOfRangeException();
        i++;
    }

    public void Take() {
        if (i >= Values.Count )
            throw new IndexOutOfRangeException();
        int v = Values[i];
        if (v > max) {
            max = v;
            value += v;
        }
        i++;
    }

    public double oracle(int m) {
    if (m <= 0) { 
        throw new IndexOutOfRangeException();
    }
    if ( i < nextOracle ) {
        throw new IndexOutOfRangeException();
    }
    if ( i + 1 + m > Values.Count ) {
        throw new IndexOutOfRangeException();
    }

    nextOracle = i + m;
    var oracleValues = new List<int>();
    for ( int l = 0; l < m; l++ )
    {
        oracleValues.Add(Values[i + 1 + l]);
    }
    return oracleValues.Average (v => v);
}

    public int Read() {
        if (i >= Values.Count )
            throw new IndexOutOfRangeException();
        return Values[i];
    }
}

Kode Game:

    void Main()
{
    var m = 0;
    for ( int l = 0; l < 1000; l++ )
    {
        var game = new Puzzle();
        var maxVal = 0;
        var lastOracle = 0;
        var lastOracleValue = 0.0m;
        var oracleValueForIOf = 0;

        for ( int i = 0; i < 10000; i++ )
        {
            var val = game.Read();
            var oracleStep = 1;
            var canUseOracle = (i - lastOracle >= oracleStep) && i + oracleStep + 1 <= 10000;
            if ( canUseOracle )
            {
                var oracle = game.oracle(oracleStep);
                lastOracle = i;
                lastOracleValue = (decimal)oracle;
                oracleValueForIOf = i + 1;
            }
            if ( TakeTheMoney(val, maxVal, oracleValueForIOf, lastOracleValue, i) )
            {
                maxVal = val;
                game.Take();
            }
            else
            {
                game.Pass();
            }
        }
        m += game.value;
    }
    ((int)(m / 1000)).Dump();
}

private bool TakeTheMoney(int val, int maxVal, int oracleValueForIOf, decimal lastOracleValue, int i)
{
    if ( val > maxVal )
    {
        if ( oracleValueForIOf != i + 1
            &&
            (val < 466.7m + (0.9352m * maxVal) + (0.0275m * i))
            )
        {
            return true;
        }

        if (oracleValueForIOf == i + 1)
        {
            if ( val < 466.7m + (0.9352m * maxVal) + (0.0275m * i) )
            {
                return true;
            }
            if ( lastOracleValue > 466.7m + (0.9352m * val) + (0.0275m * i + 1) )
            {
                if ( val < 466.7m + (0.9352m * maxVal) + (0.0275m * i + 1) )
                {
                    return true;
                }
            }
        }
    }
    return false;
}

Kredit adalah milik Reto Koradi ( /codegolf//a/54181/30910 )

Sunting: Penggunaan Dasar dari Oracle diimplementasikan. Jika oracle berikutnya di atas ambang batas untuk menggunakan memperluas amplop saat ini ke indeks Indeks Oracle. Ini tidak sering memukul tetapi ITU Peningkatan ;-)


4
Saya tidak berpikir itu sangat produktif untuk mengirim ulang solusi dari tantangan sebelumnya. Kami semua menyadari bahwa solusi-solusi itu dapat digunakan sebagai dasar untuk tantangan ini, dan saya telah meninggalkan komentar untuk OP yang menanyakan bagaimana kami harus mengatasinya. Idenya adalah bahwa Anda datang dengan solusi Anda sendiri, yang idealnya lebih baik daripada solusi untuk tantangan sebelumnya.
Reto Koradi

tolong hentikan downvoting :) note nomor 2 ditambahkan setelah kiriman saya dan karena lebih efektif daripada solusi lain - saya telah diposting di sini. tidak perlu menggunakan oracle untuk mengalahkan solusi yang ada.
Stephan Schinkel

@StephanSchinkel Anda memiliki upvote saya jika Anda berhasil memasukkan Oracle untuk meningkatkan skor saat ini. Bahkan hanya dengan $ 1.
Dorus

@BetaDecay apa sebenarnya yang disukai oleh komunitas lagi? Saya hanya mengikuti pertanyaan dari op. Sekali lagi Catatan Nomor 2 ditambahkan SETELAH kiriman saya.
Stephan Schinkel

Untuk Tidak menggunakan solusi dari bagian I kuis.
Stephan Schinkel

4

Python - $ 74112

Hanya ambil, jika nilai saat ini lebih rendah dari nilai berikutnya (yaitu Anda dapat mengambil keduanya).

def algo():
  try:
    o=oracle(1)
  except ValueError:
    take()
  r=read()
  if r>o:
    passe()
  else:
    take()

Python - (masih menghitung rata-rata)

Jawaban ini membutuhkan SANGAT PANJANG untuk menghitung. Ini mencapai sekitar $ 670.000 . Saya ingat setiap amplop yang saya lihat. Setiap kali saya harus membuat keputusan, saya menghasilkan dua daftar amplop yang tersisa yang berpotensi saya tambahkan ke dompet saya jika saya mengambil amplop saat ini atau meninggalkannya masing-masing.

Saya tidak mengoptimalkan kode.

def algo_2():
  global max_taken, past
  weight=0.92 #Empirically chosen.
  r=read()
  if len(past)==0:
    past.append(r)
    passe()
    return
  if r<max_taken:
    past.append(r)
    take() #the same as passe
    return
  coming=[x for x in range(1,10001) if x not in past and x>max_taken and x!=r ]
  comingIfTake=[x for x in range(1,10001) if x not in past and x>r ]
  if sum(coming)*weight<=sum(comingIfTake)+r:
    past.append(r)
    take()
  else:
    past.append(r)
    passe()

Dan init_game dimulai seperti ini:

def init_game():
    global stack, wallet, max_taken, oracle_turns, past
    past=[]

3
Jika Anda menggunakan set untuk merepresentasikan masa lalu, kedatangan, dan comingIfTake, dan menggunakan persimpangan, kode Anda akan jauh lebih cepat.
Nathan Merrill

4

C # - $ 780.176

Periksa apakah nilai berikutnya berada di bawah 5% dari semua nilai yang tersisa. Dapatkan lebih santai saat kita sampai akhir.

public class Taker
{
    private List<int> remaining;
    private Game game;

    public Taker(Game game)
    {
        this.game = game;
        remaining = Enumerable.Range(1, game.Size + 100).ToList();
    }

    int score = 0;

    public int PlayGame()
    {
        for (int i = 0; i < game.Size; i++)
        {
            if (game.Read() < game.Max ||
                game.Read() > selectThreshold() ||
                doOracle()
                )
            {
                remaining.Remove(game.Read());
                game.Pass();
                continue;
            }
            remaining = remaining.SkipWhile(j => j < game.Read()).ToList();
            score += game.Take();
        }
        return score;
    }

    private bool doOracle()
    {
        return game.Oracle(1) < game.Read() &&
            game.Oracle(1) > game.Max;
    }

    private int selectThreshold()
    {
        int selector = (int)(remaining.Count * 0.05);
        return remaining.ElementAt(selector);
    }
}

Dan kelas game saya, sangat jelek, kelas game bahkan tidak memvalidasi jika oracle diizinkan, tetapi karena saya hanya menggunakan Oracle (1) yang seharusnya tidak menjadi masalah.

public class Game
{
    private int[] list;
    private int position = 0;
    private int max = 0;
    public int Max { get { return max; } }
    public int Size { get { return list.Length; } }

    public Game(int[] list)
    {
        this.list = list;
    }

    public int Read()
    {
        return list[position];
    }

    public int Take()
    {
        if (list[position] < max)
        {
            position++;
            return 0;
        }
        max = list[position];
        return list[position++];
    }

    public void Pass()
    {
        position++;
    }

    public int Oracle(int M)
    {
        int next = position + 1;
        M = Math.Max(0, Math.Min(M, list.Length - next));
        return new ArraySegment<int>(list, next, M).Sum();
    }
}

4

Java, $ 804.991

Skor dari 1001 putaran. Mungkin terlalu dekat untuk menelepon antara jawaban ini dan jawaban Stephan Schinkel .

Ini didasarkan pada jawaban saya dalam tantangan sebelumnya, karena ia menggunakan perhitungan berbasis entropi yang sama untuk memperkirakan imbalan. Perbedaan utama adalah bahwa itu sekarang hanya mengambil amplop berpasangan (1 & 2, lalu 3 & 4, dan seterusnya) dan melihat kemungkinan kombinasi take-take, take-pass, pass-take, dll. Ini juga menghitung skor perkiraan tepat ketika jumlah amplop yang valid benar-benar kecil.

"Pembungkus" yang saya tulis sebenarnya bukan pembungkus sejati, itu hanya memberikan amplop berpasangan alih-alih memanggil Oracle(1)fungsi setiap putaran lainnya.

Secara keseluruhan, saya akan mengatakan bahwa, meskipun kompleksitasnya semakin meningkat, bot ini benar-benar tidak lebih baik dari bot saya sebelumnya.

Pemain

import java.lang.Math;
public class Player2
{
    public int[] V;

    public Player2(int s)
    {
        V = new int[s];
        for(int i = 0; i<V.length; i++)
        {
            V[i] = i+1;
        }
        ////System.out.println();
    }

    public boolean [] takeQ(int x, int y)
    {
        //System.out.println("Look: " + x + " " + y);
        boolean [] move = new boolean[]{false,false};
        double max = 0;
        double val = 0;
        int[] nextV = V;

        ////System.out.println("look " + x);
        int i = find(V,x);
        if(i >= 0)  //if found
        {
            //try taking first envelope
            int[] newVt = takeSlice(V,i);
            //System.out.println("  T: " + ats(newVt));
            int j = find(newVt,y);
            if(j >= 0)
            {
                //try taking first and second
                int[] newVtt = takeSlice(newVt,j);
                val = x + y + calcVal(newVtt);
                //System.out.println("  TT: " + ats(newVtt) + " " + val);
                if(val > max)
                {
                    move = new boolean[]{true,true};
                    max = val;
                    nextV = newVtt;
                }
            }
            //try taking first and passing second
            int[] newVtp = passSlice(newVt,j);

            val = x + calcVal(newVtp);
            //System.out.println("  TP: " + ats(newVtp) + " " + val);
            if(val > max)
            {
                move = new boolean[]{true,false};
                max = val;
                nextV = newVtp;
            }
        }
        int[] newVp = passSlice(V,i);
        //System.out.println("  V: " + ats(V));
        //System.out.println("  P: " + ats(newVp));
        int j = find(newVp,y);
        if(j >= 0)
        {
            //try passing first and taking second
            int[] newVpt = takeSlice(newVp,j);
            val = y + calcVal(newVpt);
            //System.out.println("  PT: " + ats(newVpt) + " " + val);
            if(val > max)
            {
                move = new boolean[]{false,true};
                max = val;
                nextV = newVpt;
            }
        }
        //try taking first and passing second
        int[] newVpp = passSlice(newVp,j);

        val = calcVal(newVpp);
        //System.out.println("  PP: " + ats(newVpp) + " " + val);
        if(val > max)
        {
            move = new boolean[]{false,false};
            max = val;
            nextV = newVpp;
        }
        V = nextV;
        //System.out.println("  NEW: " + ats(V));
        return move;
    }

    public static String ats(int [] a)
    {
        String s = "";
        for(int i = 0; i < a.length; i++)
        {
            s += a[i] + ",";
        }
        return s;
    }

    public static int[] takeSlice (int[] list, int loc)
    {
        int [] newlist = new int[list.length - loc - 1];
        for(int j = loc + 1; j < list.length; j++)
        {
            newlist[j - loc - 1] = list[j];
        }
        return newlist;
    }

    public static int[] passSlice (int[] list, int loc)
    {
        int [] newlist = list;
        if(loc >= 0)
        {
            newlist = new int[list.length-1];
            for(int k = 0; k < loc; k++)
            {
                newlist[k] = list[k];
            }
            for(int k = loc + 1; k < list.length; k++)
            {
                newlist[k-1] = list[k];
            }
        }
        return newlist;
    }

    public static double calcVal(int [] list)
    {
        if(list.length < 8)
        {
            for(int i : list)
            {
                ////System.out.print(i + ",");
            }

                ////System.out.println();
            return computeMean(list);

        }
        return smoothEstimate(list);
    }

    public static double computeMean(int[] V)
    {
        if(V.length == 1)
        {
            return V[0];
        }
        else if(V.length > 1)
        {
            double[] Es = new double[V.length];
            for(int i = 0; i < V.length; i++)
            {
                int[] newVp = new int[V.length - 1];
                for(int j = 0; j < i; j++)
                {
                    newVp[j] = V[j];
                }
                for(int j = i + 1; j < V.length; j++)
                {
                    newVp[j-1] = V[j];
                }
                double pass = computeMean(newVp);
                int[] newVt = new int[V.length - i - 1];
                for(int j = i + 1; j < V.length; j++)
                {
                    newVt[j - i - 1] = V[j];
                }
                double take = V[i] + computeMean(newVt);
                if(take > pass)
                {
                    Es[i] = take;
                }
                else
                {
                    Es[i] = pass;
                }
            }
            double sum = 0;
            for(double d : Es)
            {
                sum += d;
            }
            return sum/V.length;
        }
        else
        {
            return 0;
        }
    }

    public static double smoothEstimate(int [] list)
    {
        double total = 0;
        for(int i : list)
        {
            total+=i;
        }
        double ent = 0;
        for(int i : list)
        {
            if(i > 0)
            {
                ent -= i/total * Math.log(i/total);
            }
        }
        ////System.out.println("      total " + total);
        ////System.out.println("      entro " + Math.exp(ent));
        ////System.out.println("      count " + list.length);
        return total * Math.pow(Math.exp(ent),-0.5) * 4.0/3;// * 1.1287 + 0.05284);
    }

    public static int find(int[] list, int search)
    {
        int first  = 0;
        int last   = list.length - 1;
        int middle = (first + last)/2;

        while( first <= last )
        {
            if ( list[middle] < search )
                first = middle + 1;    
            else if ( list[middle] == search )
                break;
            else
                last = middle - 1;

            middle = (first + last)/2;
        }

        if(first > last)
        {
            return -1;
        }
        return middle;
    }
}

Pengendali

import java.lang.Math;
import java.util.Random;
import java.util.ArrayList;
import java.util.Collections;
public class Controller2
{
    public static void main(String [] args)
    {
        int size = 10000;
        int rounds = 1001;
        ArrayList<Integer> results = new ArrayList<Integer>();
        for(int round = 0; round < rounds; round++)
        {
            int[] envelopes = new int[size];
            for(int i = 0; i<envelopes.length; i++)
            {
                envelopes[i] = i+1;
            }
            shuffleArray(envelopes);
            Player2 p = new Player2(size);
            int cutoff = 0;
            int winnings = 0;
            for(int i = 0; i<envelopes.length; i+=2)
            {
                boolean [] take = p.takeQ(envelopes[i],envelopes[i+1]);
                if(take[0] && envelopes[i] >= cutoff)
                {
                    winnings += envelopes[i];
                    cutoff = envelopes[i];
                }
                if(take[1] && envelopes[i+1] >= cutoff)
                {
                    winnings += envelopes[i+1];
                    cutoff = envelopes[i+1];
                }
            }
            results.add(winnings);
        }
        Collections.sort(results);
        System.out.println(rounds + " rounds, median is " + results.get(results.size()/2));

    }

    //stol... I mean borrowed from http://stackoverflow.com/questions/1519736/random-shuffling-of-an-array
    static void shuffleArray(int[] ar)
    {
        Random rnd = new Random();
        for (int i = ar.length - 1; i > 0; i--)
        {
            int index = rnd.nextInt(i + 1);
            // Simple swap
            int a = ar[index];
            ar[index] = ar[i];
            ar[i] = a;
        }
    }
}

Alamat Bitcoin: 1BVBs9ZEP8YY4EpV868nxi2R23YfL7hdMq


3

Python 3 - $ 615570

Sebenarnya tidak menggunakan oracle ... Eh :)

def algo():
    global prevs

    try:
        prevs.append(read())
    except NameError:
        prevs = [read()]

    if len(prevs) > 10000:
        prevs = [prevs[-1]]

    if read() < round(len(prevs),-1):
        take()
    else:
        passe()

Buat daftar semua amplop sebelumnya dan periksa apakah amplop saat ini kurang dari jumlah amplop sebelumnya dalam 10 peningkatan amplop.


0

Python, 87,424

Berikut ini adalah algoritma yang sederhana dan mudah, tujuh yang beruntung.

def LuckyNumber7():
Test = read()
if "7" in str(Test):
    take()
else:
    passe()

test(LuckyNumber7)

Pada dasarnya apa yang dilakukannya adalah mengkonversi read () ke string dan memeriksa apakah ada tujuh di dalamnya. Jika ada, dibutuhkan amplop. Jika tidak, ia melewatinya.

Rata-rata sekitar 81.000, saya belum melacak.


Jadi ini menunjukkan bahwa mengandalkan keberuntungan bukanlah strategi yang sukses? ;)
Reto Koradi

@RetoKoradi Yap: D
The_Basset_Hound
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.