8

You play with up to 199 dice per player. So most of the time, the attacker will attack with 3 dice and the defender will attack with 2 dice. As long as that's the case, you could simply pick one of the three possible outcomes (with precalculated probabilities) and apply it. Outline: def _attack_(n_atk,n_def): while n_atk >= 3 and n_def >= 2: ...


7

I haven't benchmarked any of the following but I suspect that they can help you out. I'd check each alteration separately. First, selecting the number of dice (die is singular, dice is plural) as you have is confusing and probably slow. n_atk_dice = min(n_atk, 3) n_def_dice = min(n_def, 2) Second, using np.sort is (a) overkill for the problem and (b) ...


6

Preprocessing Be sure to read superb_rain's excellent answer. The following code is meant as a preprocessing. It simply iterates over every single attack & defense configuration, and calculates the cumulative probability that the attacker manages to kill 0, 1 or 2 defense soldiers. It is slow, but it's not a problem since it's only supposed to run once ...


5

The code can be structured better, so the code is more self-documenting. Self-documenting code doesn't need as many comments, which makes it easier on everyone. Comments that aren't there can't be obsolete either. Take input (height) Output pyramid Those are the only lines I want to see in main. The rest should be in functions. You started out nicely by ...


4

The implementation contains one small but important bug (or feature?), it yields the same array instance from each loop. Consider this example. int[][] numbers = new[] { new[] { 1 }, new[] { 2, 3 }, new[] { 4, 5 } }; foreach (int[] arr in Product(numbers)) { Console.WriteLine(string.Join(", ", arr)); } The output is perfect 1, 2, 4 1, 2, 5 1, ...


3

A short review; You can avoid process typeless and admin users by using an upfront .filter() obj is a terrible name (it implies the parameter is just an Object instead of an Array, list would be better, something meaningful like userDetails the best If you want to go for slightly less efficient code, you could replace the whole loop with 2 filters Dont go ...


3

It is not necessary to make a copy of seen when making a recursive call. Change seen before the recursive calls and then undo the change afterward. def dfs(x, y, seen, word = ''): """ Recursive Generator that performs a dfs on the word grid seen = set of seen co-ordinates, set of tuples word = word to yield at each recursive ...


3

Pre-compute your offset tuples for possible_directions Use type hints Use strings instead of character lists for immutable data Those aside, you should really consider avoiding printing every single line of output if possible. The printing alone, at this scale, will have a time impact. Suggested: from typing import Set, Tuple, Iterable Coords = Tuple[int, ...


3

A recursive solution seems like a good fit for this problem. public static string ReplaceOnce( string input, Dictionary<string, string> ReplacementRules) { var matches = ReplacementRules.Where(rule => input.Contains(rule.Key)); if (!matches.Any()) return input; var match = ...


2

Well, an obvious improvement is not redoing work. You are currently doing twice as much work as needed because you don't save the results of the comparisons: def confused(sys1, ann1): predicted_true, predicted_false = sys1 == 1, sys1 == 0 true_true, true_false = ann1 == 1, ann1 == 0 # True Positive (TP): we predict a label of 1 (positive), and ...


2

I think you can simplify the problem by splitting it into two parts. Part one, build a tree structure to hold your data. Part two, take the tree and spit out your paths. I knocked up a very quick example below. // A simple, specialised node class for your tree class Node { public bool Ends { get; private set; } public string Value { get; private set; ...


2

#define ERRALLOC(ptr) \ if (ptr == NULL) { \ printf("Unable to allocate memory for %s", #ptr); \ exit(1); \ } That's a poor way to handle allocation failure, and makes your function pretty much unusable in ...


2

Overall, it's a lot of effort (perhaps not in the right place) for one line. Textual data typically has lines that are very short, on the order of 80 bytes. If you're so deeply concerned about performance, you need to back out of this function and look at the I/O pattern of the calling program for more context. You'll very likely find that it's more ...


2

I find my snippet below to be direct, concise, and readable (but I rarely have any trouble reading regex patterns). The pattern literally matches the first occurring opening parenthesis, then captures one or more non-closing-parenthesis characters, then matches the required closing parenthesis. A regex approach means a single function call solution and only ...


2

Array.some In the loop when flagResumeAll becomes true nothing more will change thus it is best to exit the loop. If flagResumeAll is already true then nothing can be done inside the loop so you should not even start it. The same with type if not 0 or 1 then the loop will do nothing. Using the first example as a guide to what your code should do you can use ...


1

You could use a set as lst1 instead of a list. Every time you check if n is in lst1, it’s \$ O(n) \$ time complexity. Using a set instead will lower that to \$ O(1) \$.


1

What does line_size represent? String length (like strlen()), string size or what? With input "abc\n", *line_buffer is "abc" and line_size is 4. With input "abc" End-of-file, *line_buffer is "abc" and line_size is 3. Input error - non handling When fgets() returns NULL due to an input error, consider also returning 0 ...


1

If you profile the code without using njit, you will find that most of the time is consumed in calls to randint and sort: atk_rolls = sort[n_atk_dice](np.random.randint(1, 7, n_atk_dice)) def_rolls = sort[n_def_dice](np.random.randint(1, 7, n_def_dice)) So, instead of generating and sorting those random numbers for each loop iteration, you could pregenerate ...


1

Another possible solution is to use a Trie. Using a Trie costs more in setup and space than the original solution but if we are going to be processing a lot of strings with the same set of rules, the cost of setup becomes less of an issue. Another advantage of the Trie approach is that processing an individual input scales with the length of the input and ...


1

Looks good - you're using only simple integer addition and subtraction. Except for the division hidden here: std::cout << i << '\n'; Note that division by a constant isn't necessarily as expensive as you think: it's always possible for an optimising compiler to implement it in terms of multiplication and bitwise operations. And a test for ...


Only top voted, non community-wiki answers of a minimum length are eligible