ECE302 -- Proj1
Steven Lee & Jonathan Lam; Prof. Keene; 1/29/21
Contents
See accompanying PDF.
http://files.lambdalambda.ninja/reports/20-21_spring/ece302_proj1.lam_lee.pdf
clc; clear; N = 100000; % number of trials D = 3; % number of dice to take the sum of T = 3; % number of trials (in fun method) S = 6; % number of skills F = 6; % number of faces on the die
1a
q1a_exact = 1 / 6^D; rolls = roll_dice([N D], F); % random simulation q1a_est = sum(sum(rolls, 2) == 18) / N; print_res('1a', q1a_exact, q1a_est);
1b
q1b_exact = 1 - (1/216)^0*(215/216)^T;
rolls = roll_dice([N*T D], F);
three_roll_sums = reshape(sum(rolls, 2) == 18, N, T);
q1b_est = sum(sum(three_roll_sums, 2) >= 1) / N;
print_res('1b', q1b_exact, q1b_est);
Question 1b: Exact: 0.013825; Estimate: 0.013810; % Err: 0.106243%
1c
For both this question and the 1d: Both the exact (analytical) and simulated values are 0.000000 to 6 digits of precision; this is due to the probability being a small number raised to the sixth power. If we set S to a smaller value (e.g., S=1 or S=2), we see that the exact and simulated values match.
q1c_exact = (q1b_exact)^S;
rolls = roll_dice([N*T*S D], F);
three_roll_sums = reshape(sum(rolls, 2) == 18, [], T);
ability_scores = reshape(sum(three_roll_sums, 2) >= 1, [], S);
q1c_est = sum(sum(ability_scores, 2) == S) / N;
print_res('1c', q1c_exact, q1c_est);
Question 1c: Exact: 0.000000; Estimate: 0.000000; % Err: 100.000000%
1d
P(all <= 9) - P(all <= 9 && none == 9)
q1d_exact = ((81/216)^T - ((81-25)/216)^T)^S;
rolls = roll_dice([N*T*S D], F);
three_roll_sums = reshape(sum(rolls, 2), [], T);
ability_scores = reshape(max(three_roll_sums, [], 2) == 9, [], S);
q1d_est = sum(sum(ability_scores, 2) == S) / N;
print_res('1d', q1d_exact, q1d_est);
Question 1d: Exact: 0.000000; Estimate: 0.000000; % Err: 100.000000%
2a
D_T = 1; % number of dice trolls use F_T = 4; % number of faces on troll die D_K = 2; % number of dice Keene uses F_K = 2; % number of faces on Keene die % average hitpoints for trolls q2a_exact = (1*1 + 2*1 + 3*1 + 4*1) / 4; rolls = roll_dice([N, D_T], F_T); q2a_est = mean(sum(rolls, 2)); print_res('2a: avg. troll hp', q2a_exact, q2a_est); % average damage from fireball q2a_exact = (2*1 + 3*2 + 4*1) / 4; rolls = roll_dice([N, D_K], F_K); q2a_est = mean(sum(rolls, 2)); print_res('2a: avg. fb dmg', q2a_exact, q2a_est); % probability of dealing more than 3 damage with a fireball q2a_exact = 1/4; rolls = roll_dice([N, D_K], F_K); q2a_est = sum(sum(rolls, 2) > 3) / N; print_res('2a: P(dmg > 3)', q2a_exact, q2a_est);
Question 2a: avg. troll hp: Exact: 2.500000; Estimate: 2.496060; % Err: 0.157600% Question 2a: avg. fb dmg: Exact: 3.000000; Estimate: 3.002010; % Err: 0.067000% Question 2a: P(dmg > 3): Exact: 0.250000; Estimate: 0.251620; % Err: 0.648000%
2b
q2b_exact = ones(1, 4) / 4; rolls = roll_dice([N D_T], F_T); q2b_est = histcounts(sum(rolls, 2), 'BinMethod', 'integers') / N; fprintf('2b: Histogram of Troll HPs (hp={1,2,3,4})\n'); q2b_exact q2b_est q2b_exact = [0.25 0.5 0.25]; rolls = roll_dice([N D_K], F_K); q2b_est = histcounts(sum(rolls, 2), 'BinMethod', 'integers') / N; fprintf('2b: Histogram of Firebolt Damage (dmg={2,3,4})\n'); q2b_exact q2b_est
2b: Histogram of Troll HPs (hp={1,2,3,4}) q2b_exact = 0.2500 0.2500 0.2500 0.2500 q2b_est = 0.2516 0.2477 0.2506 0.2501 2b: Histogram of Firebolt Damage (dmg={2,3,4}) q2b_exact = 0.2500 0.5000 0.2500 q2b_est = 0.2514 0.4993 0.2493
2c
given the trolls, life, we willl evaluate whether or not the fireball can kill the trolls then we do that trial 6 times
%given troll health is 1 or 2, trolls always die, if health is % 3 then 75% and if health is 4, then 25% q2c_exact = 0.25*(1/2)^6+0.5*(3/4)^6+0.25; rolls_troll = reshape(roll_dice([N*6 D_T], F_T), [] ,6); rolls_fire = sum(roll_dice([N D_K], F_K),2); diff = rolls_troll - rolls_fire; maximum = max(diff, [], 2); q2c_est = 1- sum(maximum > 0)/N; print_res('2c', q2c_exact, q2c_est);
Question 2c: Exact: 0.342896; Estimate: 0.340680; % Err: 0.646117%
2d
scenarios for 5 dying, one surviving: note that it is only possible that FB=2 or 3 and HP=3 or 4 define the following events: a := HP=4, FB=3, all other HP<=3; P(a) = (1/4)(1/2)(3/4)^5 b := HP=4, FB=2, all other HP<=2: P(b) = (1/4)(1/4)(1/2)^5 c := HP=3, FB=2, all other HP<=2: P(c) = (1/4)(1/4)(1/2)^5 = P(b) P(d) := P(HP=4 ^ 5 dying, one surviving) = P(a) + P(b) P(e) := P(HP=3 ^ 5 dying, one surviving) = P(c) P(f) := P(5 dying, one surviving) = P(a ^ b ^ c) = P(a) + P(b) + P(c) E[HP | 5 dying, 1 surviving] = 4*P(d)/P(f) + 3*P(e)/P(f) (+ 2*0 + 1*0)
Pa = 1/4 * 1/2 * (3/4)^5; Pb = 1/4 * 1/4 * (1/2)^5; Pc = Pb; Pd = Pa + Pb; Pe = Pc; Pf = Pa + Pb + Pc; q2d_exact = 4*Pd/Pf + 3*Pe/Pf; rolls_T = roll_dice([N*6 D_T], F_T); rolls_K = roll_dice([N D_K], F_K); % in simulation, need to select the cases where exactly 5 die troll_hp = reshape(sum(rolls_T, 2), [], 6); fire_dmg = sum(rolls_K, 2); matches = troll_hp - fire_dmg; matches_where_1_troll_wins = sum(matches > 0, 2) == 1; matches = matches(matches_where_1_troll_wins, :); troll_hp = troll_hp(matches_where_1_troll_wins, :); q2d_est = mean(troll_hp(matches > 0)); print_res('2d', q2d_exact, q2d_est);
Question 2d: Exact: 3.941818; Estimate: 3.940868; % Err: 0.024094%
2e
D_SoT = 2; % Sword of Tuition D_HTD = 1; % Hammer of Tenure Denial D_hit = 1; % to hit Keene with sword or hammer F_SoT = 6; F_HTD = 4; F_hit = 20; q2e_exact = 1/2*(3.5+3.5) + 1/2*1/2*(2.5); % calculate extra dice rolls here for simplicity; however, due to % independence it doesn't make affect the result rolls_hit = reshape(sum(roll_dice([N*2 D_hit], F_hit), 2), [], 2); rolls_SoT = sum(roll_dice([N D_SoT], F_SoT), 2); rolls_HTD = sum(roll_dice([N D_HTD], F_HTD), 2); SoT_damage = rolls_SoT(rolls_hit(:, 1) >= 11); HTD_damage = rolls_HTD((rolls_hit(:, 1) >= 11) & (rolls_hit(:, 2) >= 11)); q2e_est = (sum(SoT_damage) + sum(HTD_damage)) / N; print_res('2e', q2e_exact, q2e_est);
2f
when u play dnd with us :)
% helper function function print_res(question, exact, est) pct_err = abs((est - exact) / exact * 100); fprintf('Question %s: Exact: %f; Estimate: %f; %% Err: %f%%\n', ... question, exact, est, pct_err); end % usage: roll_dice([x y]) function res = roll_dice(shape, faces) res = randi(faces, shape); end
Question 1a: Exact: 0.004630; Estimate: 0.004790; % Err: 3.464000%