Kaynaştırıcı Havai Fişekler


13

genel bakış

Havai fişeklerin a-zve zamanların bir listesi verildiğinde 3-78, hepsini doğru zamanda yanmaları için sigortalarla düzenleyin.

Bir girdi satırı, boşlukla ayrılmış harfler ve sayılar olarak verilir:

a 3 b 6 c 6 d 8 e 9 f 9

Bu örnek gösterir o havai fişek aanda ışık ihtiyacı 3, bve cher ikisi de 6, den 8, ile eve fhem de 9. Her çizgi bir haritaya karşılık gelir.

Çıktı, her bir satır için, |-sigortaları göstermek için sembolleri ve havai fişekleri göstermek için harfleri kullanan bir sigorta / havai fişek haritasıdır .

Bir -sigorta doğrudan sol / sağ olan sigortalara ve havai fişeklere |bağlanırken, sigorta yukarı / aşağı sigortalara bağlanır. Örneğin, sigortalar ||edilir değildir bağlı ve -| vardır .

Örneğin, yukarıdaki iki olası cevap şunlardır:

---a        ---------f
  |         |||   ||
  |-c       |||   de
--|--d      a||
| b |        |c
f   e        b

Tüm sigorta haritaları -sol üst köşede bir tane ile başlamalıdır . Sigortayı yaktığınız nokta budur. Sigortanın her karakterinin yanması bir saniye alır. Gördüğünüz gibi a, her iki diyagramda da üç saniyede, baltıda vb.

Şimdi, yukarıda verilen her iki harita da verilen girdi için geçerlidir, ancak bir tanesi açıkça daha verimlidir. Sol sigorta sadece 13 adet sigorta kullanırken, sağ sigorta 20 sigorta kullanıyor.

Sigortalar yok havai fişek ile yakmak! Dolayısıyla, giriş için a 3 b 5bu geçerli değildir:

---a--b

Meydan okuma

Amacınız, tüm test vakalarında kullanılan sigorta miktarını en aza indirmektir. Kullanılan sigorta birimlerinin toplamı çok basittir.

Eğer değilse olamaz bu imkansız bir durum ya da olmasın, bir test durumu için bir harita üretmek, bu durum için puanı (örneğin yukarıda 41) tüm zamanların toplamıdır.

Beraberlik durumunda, puanlama değiştirilir, böylece en kompakt haritalar kazanılır. Tiebreak skoru her haritanın sınırlayıcı kutusunun alanıdır . Yani, en uzun çizginin uzunluğu çizgi sayısının katıdır. "İmkansız" haritalar için bu, en büyük sayının karesidir (yukarıdaki örnek için 81).

Gönderilerin bu puanlama yöntemlerinin her ikisini de bağlaması durumunda, bağlantı önceki girişe / düzenlemeye gider.

Doğrulama amacıyla programınız deterministik olmalıdır.

Test Durumları

250 test durumları vardır burada yer . Her biri 4 ila 26 havai fişek içerir. Bir havai fişek için minimum sigorta süresi 3'tür. Her durumda havai fişek zaman ve harfe göre "sıralanır", yani bdaha önce hiç yanmaz a.

Gönderirken, lütfen tam programınızı, toplam puanınızı ve (en azından) dosyada verilen ilk test vakasına ilişkin haritayı ekleyin:

a 6 b 8 c 11 d 11 e 11 f 11 g 12 h 15 i 18 j 18 k 21 l 23 m 26 n 28 o 28 p 30 q 32 r 33 s 33 t 34 

Birçok havai fişek keyfi olarak aynı anda çıkabilir mi?
Ingo Bürk

Temel olarak, evet. Test durumlarımda bunun en büyük örneğini aramadım, ama en az dört tane olduğunu biliyorum. İki sigorta arasındaki süre , her biri için% rand.nextInt(5)%440 şans 0ve% 20'dir 1,2,3.
Geobits

Sadece bir öneri: Sigortaların bağlandığı veya yön değiştirdiği yerlerde, çıkış grafiklerini IMHO'yu çok daha sezgisel kılacak bir '+' kullanırdım!
flawr

@flawr Buna izin vereceğim, eğer skoru değiştirmeyecek şekilde yapılması koşuluyla. Örneğin, havai fişeklerin üstüne / altına otomatik olarak bağlanmaması -+-yerine, ---havai fişeklere bağlamak için |yukarıda / aşağıda olması gerekir. -+-yerine -|-olduğu gibi iyidir.
Geobits

Tüm test vakaları çözülebilir mi? Örneğin, 3. sırada sönecek beş veya daha fazla havai fişek olsaydı, hepsini başlangıca yeterince yakın tutabileceğinizi sanmıyorum. Aynı şekilde, hepsine sığabilir, ancak daha sonraki havai fişekler için dışarıya giden yolu engelleyebilirler.
Martin Ender

Yanıtlar:


3

C ++

Toplam Uzunluk: 9059, Toplam Alan: 27469, Hatalar: 13.

Not: Puan, başarısızlık cezalarını içerir.


Örnek çıktı:

a 6 b 8 c 11 d 11 e 11 f 11 g 12 h 15 i 18 j 18 k 21 l 23 m 26 n 28 o 28 p 30 q 32 r 33 s 33 t 34 
------ae  
     | |  
     |---c
     b||-g
      |d| 
      f | 
    i---| 
  k---| h 
   |  j   
   |---m  
   l  | t 
     o-n| 
      |s-r
      |-| 
      p q 
Length: 39, Area: 150.

a 6 b 6 c 6 d 6 e 6 f 6 g 6 h 8 i 9 j 9 k 9 l 12 m 12 n 13 o 14 p 15 q 15 r 15 s 17 t 17 u 17 v 17 w 17 x 20 y 23 z 26 
------a  n|--w 
|d-||---k|-o|  
| g|b  |--m --x
|-|c    ||--r| 
||f     l|-q | 
||--j u--|--s|-
e|-i    |p|  y|
 h      v t  z-
Length: 56, Area: 120.

Tam çıktı: http://pastebin.com/raw.php?i=spBUidBV


Sadece kaba kuvvet çözümlerini sevmiyor musunuz? Bu basit bir geri izleme algoritmasından biraz daha fazlasıdır: yorulmak bilmeyen çalışanımız harita üzerinde hareket eder, sigortaları ve havai fişekleri gerektiği gibi yerleştirir ve herhangi bir noktada olası tüm hareketleri test eder. Neredeyse --- hamle kümesini kısıtlıyoruz ve dayanıksız durumları erken terk ediyoruz, böylece dayanılmaz uzun sürmüyor (ve özellikle de sona eriyor.) Herhangi bir döngü oluşturmamak veya istenmeyen aynı şekilde geri gelmememiz için, aynı durumu iki kez ziyaret etmememiz garantilidir. Buna rağmen, optimum bir çözüm bulmak biraz zaman alabilir, bu nedenle sonunda çok uzun sürüyorsa bir çözümü optimize etmekten vazgeçeriz.

Bu algoritmanın hala bir tavan boşluğu var. Birincisi, FRUSTRATIONparametreleri artırarak daha iyi çözümler bulunabilir . Rekabet ATM'si yok, ancak bu numaralar ne zaman ve ne zaman arttırılabilir ...

İle derleyin: g++ fireworks.cpp -ofireworks -std=c++11 -pthread -O3.

İle çalıştırın: ./fireworks.

STDIN'den girişi okur ve çıktıyı STDOUT'a yazar (muhtemelen bozuk).

/* Magic numbers */
#define THREAD_COUNT 2
/* When FRUSTRATION_MOVES moves have passed since the last solution was found,
 * the last (1-FRUSTRATION_STATES_BACKOFF)*100% of the backtracking states are
 * discarded and FRUSTRATION_MOVES is multiplied by FRUSTRATION_MOVES_BACKOFF.
 * The lower these values are, the faster the algorithm is going to give up on
 * searching for better solutions. */
#define FRUSTRATION_MOVES 1000000
#define FRUSTRATION_MOVES_BACKOFF 0.8
#define FRUSTRATION_STATES_BACKOFF 0.5

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <thread>
#include <mutex>
#include <string>
#include <sstream>
#include <cassert>

using namespace std;

/* A tile on the board. Either a fuse, a firework, an empty tile or an
 * out-of-boudns tile. */
struct tile {
    /* The tile's value, encoded the "obvious" way (i.e. '-', '|', 'a', etc.)
     * Empty tiles are encoded as '\0' and OOB tiles as '*'. */
    char value;
    /* For fuse tiles, the time at which the fuse is lit. */
    int time;

    operator char&() { return value; }
    operator const char&() const { return value; }

    bool is_fuse() const { return value == '-' || value == '|'; }
    /* A tile is vacant if it's empty or OOB. */
    bool is_vacant() const { return !value || value == '*'; }

    /* Prints the tile. */
    template <typename C, typename T>
    friend basic_ostream<C, T>& operator<<(basic_ostream<C, T>& os,
                                            const tile& t) {
        return os << (t.value ? t.value : ' ');
    }
};
/* Fireworks have the same encoding as tiles. */
typedef tile firework;
typedef vector<firework> fireworks;

/* The fuse map. It has physical dimensions (its bounding-box) but is
 * conceptually infinite (filled with empty tiles.) */
class board {
    /* The tiles, ordered left-to-right top-to-bottom. */
    vector<tile> p_data;
    /* The board dimensions. */
    int p_width, p_height;
    /* The total fuse length. */
    int p_length;

public:
    board(): p_width(0), p_height(0), p_length(0) {}

    /* Physical dimensions. */
    int width() const { return p_width; }
    int height() const { return p_height; }
    int area() const { return width() * height(); }
    /* Total fuse length. */
    int length() const { return p_length; }

    /* Returns the tile at (x, y). If x or y are negative, returns an OOB
     * tile. */
    tile get(int x, int y) const {
        if (x < 0 || y < 0)
            return {'*'};
        else if (x >= width() || y >= height())
            return {'\0'};
        else
            return p_data[y * width() + x];
    }
    /* Sets the tile at (x, y). x and y must be nonnegative and the tile at
     * (x, y) must be empty. */
    board& set(int x, int y, const tile& t) & {
        assert(x >= 0 && y >= 0);
        assert(!get(x, y));
        if (x >= width() || y >= height()) {
            int new_width = x >= width() ? x + 1 : width();
            int new_height = y >= height() ? y + 1 : height();
            vector<tile> temp(new_width * new_height, {'\0'});
            for (int l = 0; l < height(); ++l)
                copy(
                    p_data.begin() + l * width(),
                    p_data.begin() + (l + 1) * width(),
                    temp.begin() + l * new_width
                );
            p_data.swap(temp);
            p_width = new_width;
            p_height = new_height;
        }
        p_data[y * width() + x] = t;
        if (t.is_fuse())
            ++p_length;
        return *this;
    }
    board&& set(int x, int y, const tile& t) && { return move(set(x, y, t)); }

    /* Prints the board. */
    template <typename C, typename T>
    friend basic_ostream<C, T>& operator<<(basic_ostream<C, T>& os,
                                            const board& b) {
        for (int y = 0; y < b.height(); ++y) {
            for (int x = 0; x < b.width(); ++x)
                os << b.get(x, y);
            os << endl;
        }
        return os;
    }
};

/* A state of the tiling algorithm. */
struct state {
    /* The current board. */
    board b;
    /* The next firework to tile. */
    fireworks::const_iterator fw;
    /* The current location. */
    int x, y;
    /* The current movement direction. 'N'orth 'S'outh 'E'ast, 'W'est or
     * 'A'ny. */
    char dir;
};

/* Adds a state to the state-stack if its total fuse length and bounding-box
 * area are not worse than the current best ones. */
void add_state(vector<state>& states, int max_length, int max_area,
                state&& new_s) {
    if (new_s.b.length() < max_length ||
        (new_s.b.length() == max_length && new_s.b.area() <= max_area)
    )
        states.push_back(move(new_s));
}
/* Adds the state after moving in a given direction, if it's a valid move. */
void add_movement(vector<state>& states, int max_length, int max_area,
                    const state& s, char dir) {
    int x = s.x, y = s.y;
    char parallel_fuse;
    switch (dir) {
    case 'E': if (s.dir == 'W') return; ++x; parallel_fuse = '|'; break;
    case 'W': if (s.dir == 'E') return; --x; parallel_fuse = '|'; break;
    case 'S': if (s.dir == 'N') return; ++y; parallel_fuse = '-'; break;
    case 'N': if (s.dir == 'S') return; --y; parallel_fuse = '-'; break;
    }
    const tile t = s.b.get(s.x, s.y), nt = s.b.get(x, y);
    assert(t.is_fuse());
    if (nt.is_fuse() && !(t == parallel_fuse && nt == parallel_fuse))
        add_state(states, max_length, max_area, {s.b, s.fw, x, y, dir});
}
/* Adds the state after moving in a given direction and tiling a fuse, if it's a
 * valid move. */
void add_fuse(vector<state>& states, int max_length, int max_area,
                const state& s, char dir, char fuse) {
    int x = s.x, y = s.y;
    int sgn;
    bool horz;
    switch (dir) {
    case 'E': ++x; sgn = 1; horz = true; break;
    case 'W': --x; sgn = -1; horz = true; break;
    case 'S': ++y; sgn = 1; horz = false; break;
    case 'N': --y; sgn = -1; horz = false; break;
    }
    if (s.b.get(x, y))
        /* Tile is not empty. */
        return;
    /* Make sure we don't create cycles or reconnect a firework. */
    const tile t = s.b.get(s.x, s.y);
    assert(t.is_fuse());
    if (t == '-') {
        if (horz) {
            if (fuse == '-') {
                if (!s.b.get(x + sgn, y).is_vacant() ||
                    s.b.get(x, y - 1) == '|' ||
                    s.b.get(x, y + 1) == '|')
                    return;
            } else {
                if (s.b.get(x + sgn, y) == '-' ||
                    !s.b.get(x, y - 1).is_vacant() ||
                    !s.b.get(x, y + 1).is_vacant())
                    return;
            }
        } else {
            if (!s.b.get(x, y + sgn).is_vacant() ||
                s.b.get(x - 1, y) == '-' ||
                s.b.get(x + 1, y) == '-')
                return;
        }
    } else {
        if (!horz) {
            if (fuse == '|') {
                if (!s.b.get(x, y + sgn).is_vacant() ||
                    s.b.get(x - 1, y) == '-' ||
                    s.b.get(x + 1, y) == '-')
                    return;
            } else {
                if (s.b.get(x, y + sgn) == '|' ||
                    !s.b.get(x - 1, y).is_vacant() ||
                    !s.b.get(x + 1, y).is_vacant())
                    return;
            }
        } else {
            if (!s.b.get(x + sgn, y).is_vacant() ||
                s.b.get(x, y - 1) == '|' ||
                s.b.get(x, y + 1) == '|')
                return;
        }
    }
    /* Ok. */
    add_state(
        states,
        max_length,
        max_area,
        {board(s.b).set(x, y, {fuse, t.time + 1}), s.fw, x, y, dir}
    );
}
/* Adds the state after adding a firework at the given direction, if it's a
 * valid move. */
void add_firework(vector<state>& states, int max_length, int max_area,
                    const state& s, char dir) {
    int x = s.x, y = s.y;
    int sgn;
    bool horz;
    switch (dir) {
    case 'E': ++x; sgn = 1; horz = true; break;
    case 'W': --x; sgn = -1; horz = true; break;
    case 'S': ++y; sgn = 1; horz = false; break;
    case 'N': --y; sgn = -1; horz = false; break;
    }
    if (s.b.get(x, y))
        /* Tile is not empty. */
        return;
    /* Make sure we don't run into an undeliberate fuse. */
    if (horz) {
        if (s.b.get(x + sgn, y) == '-' || s.b.get(x, y - 1) == '|' ||
            s.b.get(x, y + 1) == '|')
            return;
    } else {
        if (s.b.get(x, y + sgn) == '|' || s.b.get(x - 1, y) == '-' ||
            s.b.get(x + 1, y) == '-')
            return;
    }
    /* Ok. */
    add_state(
        states,
        max_length,
        max_area,
        /* After adding a firework, we can move in any direction. */
        {board(s.b).set(x, y, {*s.fw}), s.fw + 1, s.x, s.y, 'A'}
    );
}
void add_possible_moves(vector<state>& states, int max_length, int max_area,
                        const state& s) {
    /* We add the new states in reverse-desirability order. The most
     * (aesthetically) desirable states are added last. */

    const tile t = s.b.get(s.x, s.y);
    assert(t.is_fuse());

    /* Move in all (possible) directions. */
    for (char dir : "WENS")
        if (dir) add_movement(states, max_length, max_area, s, dir);

    /* If the fuse is too short for the next firework, keep adding fuse. */
    if (t.time < s.fw->time) {
        if (t == '-') {
            add_fuse(states, max_length, max_area, s, 'N', '|');
            add_fuse(states, max_length, max_area, s, 'S', '|');
            add_fuse(states, max_length, max_area, s, 'W', '|');
            add_fuse(states, max_length, max_area, s, 'W', '-');
            add_fuse(states, max_length, max_area, s, 'E', '|');
            add_fuse(states, max_length, max_area, s, 'E', '-');
        } else {
            add_fuse(states, max_length, max_area, s, 'W', '-');
            add_fuse(states, max_length, max_area, s, 'E', '-');
            add_fuse(states, max_length, max_area, s, 'N', '-');
            add_fuse(states, max_length, max_area, s, 'N', '|');
            add_fuse(states, max_length, max_area, s, 'S', '-');
            add_fuse(states, max_length, max_area, s, 'S', '|');
        }
    } else if (t.time == s.fw->time) {
        /* If we have enough fuse for the next firework, place the firework (if
         * possible) and don't add more fuse, or else we'll never finish... */
        if (t == '-') {
            add_firework(states, max_length, max_area, s, 'W');
            add_firework(states, max_length, max_area, s, 'E');
        } else {
            add_firework(states, max_length, max_area, s, 'N');
            add_firework(states, max_length, max_area, s, 'S');
        }
    }
}

void thread_proc(mutex& lock, int& total_length, int& total_area,
                    int& failures) {
    fireworks fw;
    vector<state> states;

    while (true) {
        /* Read input. */
        string input;
        {
            lock_guard<mutex> lg(lock);

            while (!cin.eof() && input.empty())
                getline(cin, input);
            if (input.empty())
                break;
        }
        fw.clear();
        int length = 0, area;
        {
            stringstream is;
            is << input;
            while (!is.eof()) {
                char c;
                int t;
                if (is >> c >> t) {
                    /* Fireworks must be sorted by launch time. */
                    assert(fw.empty() || t >= fw.back().time);
                    fw.push_back({c, t});
                    length += t;
                }
            }
            assert(!fw.empty());
            area = fw.back().time * fw.back().time;
        }

        /* Add initial state. */
        states.push_back({board().set(0, 0, {'-', 1}), fw.begin(), 0, 0, 'A'});

        board solution;
        int moves = 0;
        int frustration_moves = FRUSTRATION_MOVES;

        while (!states.empty()) {
            /* Check for solutions (all fireworks consumed.) */
            while (!states.empty() && states.back().fw == fw.end()) {
                state& s = states.back();
                /* Did we find a better solution? */
                if (solution.area() == 0 || s.b.length() < length ||
                    (s.b.length() == length && s.b.area() < area)
                ) {
                    solution = move(s.b);
                    moves = 0;
                    length = solution.length();
                    area = solution.area();
                }
                states.pop_back();
            }

            /* Expand the top state. */
            if (!states.empty()) {
                state s = move(states.back());
                states.pop_back();
                add_possible_moves(states, length, area, s);
            }

            /* Getting frustrated? */
            ++moves;
            if (moves > frustration_moves) {
                /* Get rid of some data. */
                states.erase(
                    states.begin() + states.size() * FRUSTRATION_STATES_BACKOFF,
                    states.end()
                );
                frustration_moves *= FRUSTRATION_MOVES_BACKOFF;
                moves = 0;
            }
        }

        /* Print solution. */
        {
            lock_guard<mutex> lg(lock);

            cout << input << endl;

            if (solution.area())
                cout << solution;
            else {
                cout << "FAILED!" << endl;
                ++failures;
            }

            cout << "Length: " << length <<
                    ", Area: " << area <<
                    "." << endl << endl;
            total_length += length;
            total_area += area;
        }
    }
}

int main(int argc, const char* argv[]) {
    thread threads[THREAD_COUNT];
    mutex lock;
    int total_length = 0, total_area = 0, failures = 0;

    for (int i = 0; i < THREAD_COUNT; ++i)
        threads[i] = thread(thread_proc, ref(lock), ref(total_length),
                            ref(total_area), ref(failures));
    for (int i = 0; i < THREAD_COUNT; ++i)
        threads[i].join();

    cout << "Total Length: " << total_length <<
            ", Total Area: " << total_area <<
            ", Failures: " << failures <<
            "." << endl;
}

piton

Toplam Uzunluk: 17387, Toplam Alan: 62285, Hatalar: 44.


Örnek çıktı:

a 6 b 8 c 11 d 11 e 11 f 11 g 12 h 15 i 18 j 18 k 21 l 23 m 26 n 28 o 28 p 30 q 32 r 33 s 33 t 34
------a                
     |----f            
     |---c             
     b|||---h          
      |dg  |           
      e    |-j         
           |---k       
           i  |        
              |---m    
              l  |-o   
                 |--p  
                 n |--s
                   |-r 
                   q|  
                    t  
Length: 45, Area: 345.

Tam çıktı: http://pastebin.com/raw.php?i=mgiqXCRK


Referans olarak, burada çok daha basit bir yaklaşım var. Havai fişekleri tek bir ana sigorta hattına bağlamaya ve "merdiven" şekli oluşturmaya çalışır. Bir havai fişek ana hatta doğrudan bağlanamazsa (aynı anda iki veya daha fazla havai fişek yandığında gerçekleşir), ana hattı geriye doğru veya sağa doğru dallanabileceği bir nokta arayarak izler (ve eğer başarısız olursa) böyle bir nokta yok.)

Şaşırtıcı olmayan bir şekilde, kaba kuvvet çözücüsünden daha kötüdür, ancak büyük bir farkla değil. Dürüst olmak gerekirse, farkın biraz daha büyük olmasını bekledim.

İle çalıştırın: python fireworks.py.

from __future__ import print_function
import sys

total_length = total_area = failures = 0

for line in sys.stdin:
    # Read input.
    line = line.strip()
    if line == "": continue
    fws = line.split(' ')
    # The fireworks are a list of pairs of the form (<letter>, <time>).
    fws = [(fws[i], int(fws[i + 1])) for i in xrange(0, len(fws), 2)]

    # The board is a dictionary of the form <coord>: <tile>.
    # The first tile marks the "starting point" and is out-of-bounds.
    board = {(-1, 0): '*'}
    # The tip of the main "staircase" fuse.
    tip_x, tip_y = -1, 0
    tip_time = 0
    # We didn't fail. Yet...
    failed = False

    for (fw, fw_time) in fws:
        dt = fw_time - tip_time
        # Can we add the firework to the main fuse line?
        if dt > 0:
            # We can. Alternate the direction to create a "staircase" pattern.
            if board[(tip_x, tip_y)] == '-':    dx, dy = 0, 1; fuse = '|'
            else:                               dx, dy = 1, 0; fuse = '-'
            x, y = tip_x, tip_y
            tip_x += dt * dx
            tip_y += dt * dy
            tip_time += dt
        else:
            # We can't. Trace the main fuse back until we find a point where we
            # can thread, or fail if we reach the starting point.
            x, y = tip_x, tip_y
            while board[(x, y)] != '*':
                horz = board[(x, y)] == '-'
                if horz:    dx, dy = 0, 1; fuse = '|'
                else:       dx, dy = 1, 0; fuse = '-'
                if dt > 0 and (x + dx, y + dy) not in board: break
                if horz:    x -= 1
                else:       y -= 1
                dt += 1
            if board[(x, y)] == '*':
                failed = True
                break
        # Add the fuse and firework.
        for i in xrange(dt):
            x += dx; y += dy
            board[(x, y)] = fuse
        board[(x + dx, y + dy)] = fw

    # Print output.
    print(line)
    if not failed:
        max_x, max_y = (max(board, key=lambda p: p[i])[i] + 1 for i in (0, 1))
        for y in xrange(max_y):
            for x in xrange(max_x):
                print(board.get((x, y), ' '), end = "")
            print()
        length = len(board) - len(fws) - 1
        area = max_x * max_y
    else:
        print("FAILED!")
        failures += 1
        length = sum(map(lambda fw: fw[1], fws))
        area = fws[-1][1] ** 2
    print("Length: %d, Area: %d.\n" % (length, area))
    total_length += length; total_area += area

print("Total Length: %d, Total Area: %d, Failures: %d." %
        (total_length, total_area, failures))

Meraktan, bunun mevcut parametrelerle tamamlanması ne kadar sürer?
Geobits

@Geobits: Açıkçası makineye bağlı ve çok yakından izlemedim, ama sanırım yirmi dakika, ver ya da al.
DarwinBot
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.