Prawdopodobieństwo śmierci człowieka poruszającego się n krokami w macierzy

Istnieje wyspa, która jest reprezentowana przez kwadratową macierz nxn.

Osoba na wyspie stoi w dowolnym punkcie współrzędnych (x, y). Może poruszać się w dowolnym kierunku o jeden krok w prawo, w lewo, w górę, w dół na wyspie. Jeśli wyjdzie poza wyspę, umrze.

Niech Wyspa będzie reprezentowana jako (0,0) do (N-1,N-1) (tzn. macierz nxn) & osoba stoi przy podanych współrzędnych (x, y). Może poruszać się po wyspie n kroków (wzdłuż macierzy). Jakie jest prawdopodobieństwo, że jest martwy po tym, jak wszedł po schodach na wyspę?

Jakie powinno być podejście do znajdowania prawdopodobieństwa przy użyciu technik programowania?

Mam metodę matematyczną, ale nie wiem czy jest poprawna czy nie. Tutaj jest:

Całkowita liczba wyników wynosi n^n. aby obliczyć liczbę wyników, które mogą doprowadzić do śmierci osoby:

Dla każdego z czterech kierunków sprawdź, ile kroków może doprowadzić do wyjścia z matrycy. Następnie zastosuj wzór prawdopodobieństwa w szkole średniej. Dla np. Załóżmy, że całkowita liczba kroków jakie może wykonać to 5; (x, y) = (2,1) [indeksowanie jest oparte na 0]. Więc musi zrobić 3 kroki w północnym reż. by wypaść z wyspy. Trzymając je w grupie: (NNN) i wykonując kolejne 2 kroki jako dowolny z 4 wyborów, mamy wzór: 4*4*3. Podobnie dla pozostałych 3 kierunków. Na koniec, prawdopodobieństwo = (suma obliczonych wyników śmierci) / (total outcomes)

To był wywiad w Google pytanie.

Author: Sankalp, 2013-05-13

5 answers

TL; DR : Rekurencja. (Lub "indukcja matematyczna", jeśli jesteś snobem.)

W dalszej części "On nie żyje po krokach po wyspie" zakłada się, że "umiera po mniej lub równo po krokach po wyspie". Jeśli potraktujesz to jako "umiera po dokładnie n krokach", odpowiedź będzie nieco inna. Omówię to krótko na końcu.)

Mamy macierz NxN, gdzie wartość w każdej komórce reprezentuje prawdopodobieństwo śmierci w krokach n jeśli zaczniemy od tej celi.

Rozważmy prawdopodobieństwo śmierci w 0 krokach. Oczywiście, to jest 0.0 dla każdego miejsca wewnątrz wyspy, i 1.0 wszędzie poza nią.

Jakie jest prawdopodobieństwo śmierci w 1 krokach? Masz cztery kierunki, w których możesz się poruszać, z równym prawdopodobieństwem. Więc dla każdej komórki, bierzesz jej czterech sąsiadów, znajdujesz ich prawdopodobieństwo śmierci w krokach 0, i porównujesz je razem. (Jeśli sąsiad jest poza macierzą, rozważasz jego prawdopodobieństwo 1.0.)

Podobnie prawdopodobieństwo umierania w krokach k zaczynających się od danej komórki jest średnią prawdopodobieństwa umierania w krokach k-1 zaczynających się od sąsiednich komórek.

Kod Pythona:

from itertools import product as prod 

def prob_death(island_size, steps):
    if island_size < 1 or steps < 0: raise ValueError
    new_prob = [[0. for i in range(island_size)] for j in range(island_size)]
    if steps == 0:
        return new_prob
    old_prob = prob_death(island_size, steps - 1)
    directions = [(0, -1), (1, 0), (0, 1), (-1, 0)]
    for (i, j, direction) in prod(range(island_size), range(island_size), directions):
        neighbor_i = i + direction[0]
        neighbor_j = j + direction[1]
        if neighbor_i >= 0 and neighbor_i < island_size and \
                neighbor_j >= 0 and neighbor_j < island_size:
            prob_death_this_way = old_prob[neighbor_i][neighbor_j]
        else: # neighbor is outside the island 
            prob_death_this_way = 1.
        new_prob[i][j] += 0.25* prob_death_this_way
    return new_prob

Teraz przetestujmy to trochę: (mpr jest tylko funkcją do ładnie drukowanych matryc)

>>> mpr(prob_death(5, 0))
0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000

Zgodnie z oczekiwaniami: nie możesz umrzeć w 0 krokach, jeśli zaczniesz wewnątrz Wyspy.

>>> mpr(prob_death(5,1))
0.500000 0.250000 0.250000 0.250000 0.500000
0.250000 0.000000 0.000000 0.000000 0.250000
0.250000 0.000000 0.000000 0.000000 0.250000
0.250000 0.000000 0.000000 0.000000 0.250000
0.500000 0.250000 0.250000 0.250000 0.500000
Tego byśmy się spodziewali. Jeśli zaczniesz od w narożnej celi masz 0.5 prawdopodobieństwo śmierci w 1 kroku: 2 z 4 sąsiadów jest poza wyspą. Jeśli zaczynasz na krawędzi, tylko 1 sąsiad jest na zewnątrz, więc prawdopodobieństwo śmierci wynosi 0.25. Wszędzie indziej wszyscy sąsiedzi są wewnątrz wyspy, więc prawdopodobieństwo śmierci w 1 kroku wynosi 0.0.
>>> mpr(prob_death(5, 5))
0.806641 0.666016 0.622070 0.666016 0.806641
0.666016 0.437500 0.349609 0.437500 0.666016
0.622070 0.349609 0.261719 0.349609 0.622070
0.666016 0.437500 0.349609 0.437500 0.666016
0.806641 0.666016 0.622070 0.666016 0.806641
Prawdopodobieństwo śmierci w 5 krokach. Nie mogę zweryfikować dokładnych wartości, ale wygląda to mniej więcej tak: prawdopodobieństwo śmierci jest najwyższe w narożnikach, nieco niższe w krawędzie i zmniejsza się równomiernie do wewnątrz.

To rozwiązuje problem umierania w mniejszych lub równych krokach n.

Teraz, aby znaleźć prawdopodobieństwo śmierci w dokładnie n kroki: niech prawdopodobieństwo śmierci w mniejszych lub równych n krokach zaczynających się od (x,y) będzie oznaczane przez P(x,y,n). Wtedy prawdopodobieństwo śmierci w dokładnie n krokach jest prawdopodobieństwem przeżycia w n-1 krokach, razy prawdopodobieństwo śmierci w n tym kroku biorąc pod uwagę, że przeżyliśmy dla n-1 kroków: (1-P(x,y,n-1))*(P(x,y,n) - P(x,y,n-1)). (Nie jestem pewien tego wzoru; popraw mnie, jeśli się mylę.)

 9
Author: Anubhav C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-14 14:07:28

Po pierwsze, zacznij od macierzy z prawdopodobieństwem bycia w kwadracie (x, y) w 0 kroku. Zasymulujmy to matrycą 4x4. Zakładając, że facet zaczyna od (1, 2):

After 0 steps:
  0.00%   0.00%   0.00%   0.00%
  0.00%   0.00% 100.00%   0.00%
  0.00%   0.00%   0.00%   0.00%
  0.00%   0.00%   0.00%   0.00%
outside:   0.00%
----
After 1 steps:
  0.00%   0.00%  25.00%   0.00%
  0.00%  25.00%   0.00%  25.00%
  0.00%   0.00%  25.00%   0.00%
  0.00%   0.00%   0.00%   0.00%
outside:   0.00%
----
After 2 steps:
  0.00%  12.50%   0.00%  12.50%
  6.25%   0.00%  25.00%   0.00%
  0.00%  12.50%   0.00%  12.50%
  0.00%   0.00%   6.25%   0.00%
outside:  12.50%
----
After 3 steps:
  4.69%   0.00%  12.50%   0.00%
  0.00%  14.06%   0.00%  12.50%
  4.69%   0.00%  14.06%   0.00%
  0.00%   4.69%   0.00%   4.69%
outside:  28.12%
----
After 4 steps:
  0.00%   7.81%   0.00%   6.25%
  5.86%   0.00%  13.28%   0.00%
  0.00%   9.38%   0.00%   7.81%
  2.34%   0.00%   5.86%   0.00%
outside:  41.41%
----

Oto program Pythona, który oblicza to:

class Table:
    def __init__(self, n, outside=0):
        self.T = [[0]*n for i in xrange(n)]
        self.outside = outside

    def add(self, i, j, value):
        n = len(self.T)
        if 0<=i<n and 0<=j<n:
            self.T[i][j] += value
        else:
            self.outside += value

    def make_next(self):
        n = len(self.T)
        Q = Table(n, self.outside)

        for i in xrange(n):
            for j in xrange(n):
                value = self.T[i][j] / 4.0
                Q.add(i-1, j, value)
                Q.add(i+1, j, value)
                Q.add(i, j-1, value)
                Q.add(i, j+1, value)
        return Q

    def __repr__(self):
        return '\n'.join(' '.join(
                    '{:6.2f}%'.format(item*100) 
                    for item in line)
                    for line in self.T) + \
               '\noutside: {}'.format('{:6.2f}%'.format(self.outside*100))


N = 4
T = Table(N)
T.add(1, 2, 1)

for k in xrange(N+1):
    print 'After {} steps:'.format(k)
    print T
    print '----'

    T = T.make_next()
 1
Author: Juan Lopes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-14 03:13:38

Jest to bardzo złożony i niuansowy problem -- podejrzewam, że celem ankieterów nie było usłyszenie, jak wymyślisz odpowiedź, ale raczej zobaczyć, jak podchodzisz do problemu.

Problem staje się szachownicą N kwadraty na boku, z pozornie przypadkowym rozmieszczeniem części, która musi poruszać się N spacjami, poruszając się w pozornie przypadkowym kierunku kardynalnym każdego obrotu. Prawdopodobieństwo, że element opuści planszę jest więc związane nie tylko z wielkością deska, ale umieszczenie elementu. Ponieważ każdy ruch poza planszą również liczy się jako opuszczenie planszy, Ścieżka jest zatem istotna również.

Dla siatki 2×2, pionek ma 2/7 prawdopodobieństwa pozostania na planszy (cztery ścieżki pozostają na planszy, czternaście ścieżek ogółem, niezależnie od tego, który z czterech możliwych punktów początkowych).

Dla siatki 3×3, element ma 2/11 prawdopodobieństwo pozostania na planszy (16 ścieżek pozostaje na, 88 wszystkich ścieżek) jeśli zaczyna się na rogu. Jeśli zaczyna się na stronie, ma prawdopodobieństwo 3/11 (24 ścieżki pozostają na). Jeśli zaczyna się w centrum, ma prawdopodobieństwo 9/22 (36 ścieżek pozostaje na). Ponieważ każdy element ma 4/9 prawdopodobieństwa rozpoczęcia w rogu lub na boku, a 1/9 prawdopodobieństwo rozpoczęcia w centrum, jego całkowite prawdopodobieństwo pozostania na planszy jest (2/11 + 3/11) × 4/9 + 9/22 × 1/9 = 0.247.

Siatka 4×4 staje się (oczywiście) jeszcze bardziej skomplikowana, ale być może warto zauważyć, że siatki są zgodne ze wzorem:

2×2:

- - 1 - -
- 2 - 2 -
1 - 2 - 1
- 2 - 2 -
- - 1 - -

3×3:

- - - 1 - - -
- - 3 - 3 - -
- 3 - 9 - 3 -
1 - 9 - 9 - 1
- 3 - 9 - 3 -
- - 3 - 3 - -
- - - 1 - - -

Zacząłem na siatce 4×4, ale nie dzięki. Plac startowy wydaje się mieć 36 ścieżek prowadzących do niego, a ich identyfikacja jest, cóż, żmudna. W każdym przypadku element zaczyna się na środku wzoru i możemy narysować planszę według własnego uznania.

Jest jednak ewidentnie wzorzec i dość krzyczy, że istnieje symetria matematyczna, ale nie mam ani czas ani cierpliwość, aby to wypracować. Każdy biegun ma jedną ścieżkę, następna grupa punktów końcowych ma N ścieżki, a następna grupa wydaje się mieć n2 / align = "left" / Podejrzewam, że popełniłem błąd w liczeniu najbardziej wewnętrznego zestawu punktów końcowych dla siatki 4×4, ale jeśli nie, 36 = n (n - 1)2, co sugeruje wzór pierścieni.

Tak czy inaczej, jak powiedziałem, problem jest bardzo skomplikowany i prawie na pewno twoje podejście było oceniane, nie potrafisz odpowiedzieć. Mimo to, to było zabawne ćwiczenie.
 0
Author: cabbagery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-14 03:07:52

Podejście powinno opierać się na wzorze probabilistycznym-liczba przypadków korzystnych / całkowita liczba przypadków

Podane współrzędne (x, y) i stopnie-n Całkowita liczba sposobów, w jakie użytkownik może podjąć kroki -
1. Krok - 4 sposoby 2. Krok-4 * 3 (zakładając, że nie może zrobić kroku wstecz) 3. Krok - 4 * 3^2 ... .... ... nth Krok - 4*3^(n-1) Artmetic progresji daje całkowite kroki.

Farovable cases - tj. przekraczanie granic-funkcja rekurencyjna z rekurencją na wszystkich 4 kierunkach i zmiennej incr policz za każdym razem, gdy granica macierzy zostanie przekroczona.

Podziel oba, aby uzyskać odpowiedź.

 0
Author: Mudit Verma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-28 09:06:44

Dzięki Anubhav C za świetne rozwiązanie powyżej, które było bardzo pomocne w oświetleniu rozwiązania problemu. Myślę, że użycie 0,25 jako prawdopodobieństwa (o którym mowa powyżej ) może być mylące i błędne! Jeśli spojrzymy na prawdopodobieństwo # dead_cases/ # total_possible_moves, wyniki będą różne.

Rozważ następujący kod do znajdowania przypadków śmierci / przetrwania:

def winLoss_stat(N, steps):
    newStats = [[[0, 0, 0] for i in range(N)] for j in range(N)]
    if steps==0:
        newStats = [[[1, 0, 0] for i in range(N)] for j in range(N)]
        return newStats
    oldStats = winLoss_stat(N, steps-1)
    for i in range(N):
        for j in range(N):
            for d in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
                indX = i + d[0]
                indY = j + d[1]
                if indX >=0 and indX < N and indY >= 0 and indY<N:
                    newStats[i][j][0] += oldStats[indX][indY][0]
                    newStats[i][j][1] += oldStats[indX][indY][1]
                    newStats[i][j][2] += oldStats[indX][indY][2]
                else:
                    newStats[i][j][1] += 1
                    if steps==1:
                        newStats[i][j][2] = 1
    return newStats

(or equivalently, for one step (using dfs - recursive):

class winLoss:
    def __init__(self, N):
        self.win = 0 
        self.loss = 0
        self.N = N
    def winLoss(self, x, y, n):
        if x < 0 or y < 0 or x >= self.N or y >= self.N:
            self.loss += 1
            return
        if n == 0:
            self.win += 1
            return
        self.winLoss(x - 1, y, n-1)
        self.winLoss(x, y - 1, n-1)
        self.winLoss(x+1, y, n-1)
        self.winLoss(x, y+1, n-1)



    wl = winLoss(n)
    wl.winLoss(i, j, n)
for any i,j start point and n (size of square)
)

The winLoss_stat returns three values for starting point at each square i, j: 
[numbers of survive cases, numbers of die cases before or at k steps, numbers of death exactly at step k]

The results are as the following for n=4 (4X4), steps=4:

              0              1              2             3
0  [58, 24, 12]   [93, 34, 18]   [93, 34, 18]  [58, 24, 12]
1  [93, 34, 18]  [150, 46, 28]  [150, 46, 28]  [93, 34, 18]
2  [93, 34, 18]  [150, 46, 28]  [150, 46, 28]  [93, 34, 18]
3  [58, 24, 12]   [93, 34, 18]   [93, 34, 18]  [58, 24, 12]

This translates to the following probabilities for 
1. death before or at k steps:
          0         1         2         3
0  0.292683  0.267717  0.267717  0.292683
1  0.267717  0.234694  0.234694  0.267717
2  0.267717  0.234694  0.234694  0.267717
3  0.292683  0.267717  0.267717  0.292683

2. death exactly at k steps:
          0         1         2         3
0  0.146341  0.141732  0.141732  0.146341
1  0.141732  0.142857  0.142857  0.141732
2  0.141732  0.142857  0.142857  0.141732
3  0.146341  0.141732  0.141732  0.146341

The results can be verified by looking at the numbers of win-loss from step 1 to 3 for n=3:

winLoss_stat(3, 1)
           0          1          2
0  [2, 2, 1]  [3, 1, 1]  [2, 2, 1]
1  [3, 1, 1]  [4, 0, 0]  [3, 1, 1]
2  [2, 2, 1]  [3, 1, 1]  [2, 2, 1]

winLoss_stat(3, 2)
           0           1          2
0  [6, 4, 2]   [8, 5, 2]  [6, 4, 2]
1  [8, 5, 2]  [12, 4, 4]  [8, 5, 2]
2  [6, 4, 2]   [8, 5, 2]  [6, 4, 2]

winLoss_stat(3, 3)
             0            1            2
0  [16, 12, 4]  [24, 13, 8]  [16, 12, 4]
1  [24, 13, 8]  [32, 20, 8]  [24, 13, 8]
2  [16, 12, 4]  [24, 13, 8]  [16, 12, 4]
 0
Author: ElPred,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-23 23:36:18