Dice simulator

This commit is contained in:
Jan-Niclas Loosen
2025-10-24 20:58:31 +02:00
parent 49438ccaaf
commit 90ce78f17d
9 changed files with 312 additions and 6 deletions

60
Uebung-02/dice.cpp Normal file
View File

@@ -0,0 +1,60 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <random>
#include <map>
#include <set>
#include <string>
#include <vector>
class Dice {
std::vector<std::string> sides;
std::vector<double> probs;
std::mt19937 gen;
std::discrete_distribution<> dist;
public:
size_t accepted = 0;
size_t rejected = 0;
Dice(const std::vector<std::string>& sides, const std::vector<double>& probs)
: sides(sides), probs(probs), gen(std::random_device{}()), dist(probs.begin(), probs.end()) {}
std::string fair_dice() {
while (true) {
std::vector<std::string> res;
for (size_t i = 0; i < sides.size(); ++i)
res.push_back(sides[dist(gen)]);
std::set<std::string> uniq(res.begin(), res.end());
if (uniq.size() == res.size()) {
++accepted;
return res[0];
}
++rejected;
}
}
std::map<std::string,int> throw_dice(int n) {
std::map<std::string,int> res;
for (auto& s : sides) res[s] = 0;
for (int i = 0; i < n; ++i)
res[fair_dice()]++;
return res;
}
std::pair<size_t,size_t> stats() const { return {accepted, rejected}; }
void reset_stats() { accepted = rejected = 0; }
};
namespace py = pybind11;
PYBIND11_MODULE(dice, m) {
py::class_<Dice>(m, "Dice")
.def(py::init<const std::vector<std::string>&, const std::vector<double>&>())
.def("fair_dice", &Dice::fair_dice)
.def("throw_dice", &Dice::throw_dice)
.def("stats", &Dice::stats)
.def("reset_stats", &Dice::reset_stats)
.def_readwrite("accepted", &Dice::accepted)
.def_readwrite("rejected", &Dice::rejected);
}

36
Uebung-02/dice.py Normal file
View File

@@ -0,0 +1,36 @@
from lib.Natives import NativeLoader
def throw_dice_cpp(n: int, sides: list, probs: list):
loader = NativeLoader()
dice_mod = loader.cpp("dice")
Dice = dice_mod.Dice
d = Dice(sides, probs)
d.reset_stats()
res = d.throw_dice(n)
accepted, rejected = d.stats()
return res, accepted, rejected
dice_sides = ['1', '2', '3', '4', '5', '6']
dice_props = [0.1, 0.1, 0.1, 0.1, 0.1, 0.5]
coin_sides = ['Head', 'Number']
coin_head = [0.1, 0.5]
rep = 100000
# --- Dice test ---
res_cpp, acc_dice, rej_dice = throw_dice_cpp(rep, dice_sides, dice_props)
total = sum(res_cpp.values())
probs_estimated = {k: v / total for k, v in res_cpp.items()}
print("C++ Dice result (relative):", probs_estimated)
print(f"Accepted: {acc_dice/(acc_dice+rej_dice)*100:.2f}%, "
f"Rejected: {rej_dice/(acc_dice+rej_dice)*100:.2f}%\n")
# --- Coin test ---
res_coin, acc_coin, rej_coin = throw_dice_cpp(rep, coin_sides, coin_head)
total_coin = sum(res_coin.values())
probs_coin = {k: v / total_coin for k, v in res_coin.items()}
print("C++ Coin result (relative):", probs_coin)
print(f"Accepted: {acc_coin/(acc_coin+rej_coin)*100:.2f}%, "
f"Rejected: {rej_coin/(acc_coin+rej_coin)*100:.2f}%")

27
Uebung-02/minsearch.py Normal file
View File

@@ -0,0 +1,27 @@
import random
numsTest = [1, 2, 3, 4, 5]
def search_min(nums):
if len(nums) == 1:
return nums[0]
num = nums[0]
nums.remove(num)
# n-1 recursions
rec_num = search_min(nums)
if rec_num < num:
return rec_num
else:
# n-1 times called in worst case
smaller = True
for n in nums:
if n <= num:
smaller = False
print('Hit')
assert smaller == True
return num
print(search_min(numsTest))