Edit: Now I think this is a sweep line problem. (see update2 at the bottom)
In this problem we are given N objects and M constraints. (N can be 200k, M can be 100k). Each object is either black, or white. Each constraint is in the form (x, y) and means that in the range of objects x..y, there is exactly one white object; the rest are black. We would like to determine the maximum number of white objects that can exist, or if it isn't possible to satisfy the constraints.
I observe that if a constraint is fully contained in another, the inner constraint will dictate where a white object can be placed. Also, if there are several non-intersecting constraints contained within another, it should be impossible since it violates the fact that there can only be one white object per constraint. The algorithm should be fast enough to run under 2-3 seconds.
Update: One of the answers mentions the exact cover problem; is this a specialized instance that isn't NP-complete?
Update2: If we change each constraint into a begin and end event, and sort these events, could we just systematically sweep across these events and assign white objects?
You problem can be expressed as an exact cover problem: the constraint intervals form the set to be covered, and each white object covers those constraint intervals which it falls inside of. Your problem, then, is to find a subset of the white objects which covers each constraint interval exactly once.
Exact cover problems in general are NP-complete, although that obviously doesn't necessarily mean that any specific subset of them are. However, there nonetheless exist algorithms, such as Knuth's Algorithm X (as implemented by dancing links) that can solve most such problems quite efficiently.
It's possible that the one-dimensional structure of your problem might also allow more straightforward specialized solution methods. However, Algorithm X is a very good general tool for attacking such problems. (For example, the fastest sudoku solvers typically use something like it.)
Yes, there's a (point)-sweep algorithm. This one is sort of inelegant, but I think it works.
First, sweep for nested intervals. Process begin and end events in sorted order (tiebreakers left to you) and keep a list of active intervals not known to contain another interval. To handle a begin event, append the corresponding interval. To handle an end event, check whether the corresponding interval I has been removed. If not, remove I and all of the remaining intervals J before I from the list. For each such J, append two intervals whose union is the set difference J \ I to a list of blacked out intervals.
Second, sweep to contract the blacked out intervals. In other words, delete the objects known to be black, renumber, and adjust the constraints accordingly. If an entire constraint is blacked out, then there is no solution.
Third, sweep to solve the problem on what are now non-nested intervals. The greedy solution is provably optimal.
Example: suppose I have half-open constraints [0, 4), [1, 3), [2, 5). The first sweep creates blackouts [0, 1) and [3, 4). The second sweep leaves constraints [a, c), [a, c), [b, d).* The greedy sweep places white objects at new locations a, c, d (old locations 1, 4, 5).
Illustration of the second sweep:
0 1 2 3 4 5 old coordinates
[ )
[ )
[ )
** ** blackouts
a b c d new coordinates
[ )
[ )
[ )
Related
I'm trying to find an algorithm to the following problem.
Say I have a number of objects A, B, C,...
I have a list of valid combinations of these objects. Each combination is of length 2 or 4.
For eg. AF, CE, CEGH, ADFG,... and so on.
For combinations of two objects, eg. AF, the length of the combination is 2. For combination of four objects, eg CEGH, the length of the combination.
I can only pick non-overlapping combinations, i.e. I cannot pick AF and ADFG because both require objects 'A' and 'F'. I can pick combinations AF and CEGH because they do not require common objects.
If my solution consists of only the two combinations AF and CEGH, then my objective is the sum of the length of the combinations, which is 2 + 4 = 6.
Given a list of objects and their valid combinations, how do I pick the most valid combinations that don't overlap with each other so that I maximize the sum of the lengths of the combinations? I do not want to formulate it as an IP as I am working with a problem instance with 180 objects and 10 million valid combinations and solving an IP using CPLEX is prohibitively slow. Looking for some other elegant way to solve it. Can I perhaps convert this to a network? And solve it using a max-flow algorithm? Or a Dynamic program? Stuck as to how to go about solving this problem.
My first attempt at showing this problem to be NP-hard was wrong, as it did not take into account the fact that only combinations of size 2 or 4 were allowed. However, using Jim D.'s suggestion to reduce from 3-dimensional matching (3DM), we can show that the problem is nevertheless NP-hard.
I'll show that the natural decision problem form of your problem ("Given a set O of objects, and a set C of combinations of either 2 or 4 objects from O, and an integer m, does there exist a subset D of C such that all sets in D are pairwise disjoint, and the union of all sets in D has size at least m?") is NP-hard. Clearly the optimisation problem (i.e., your original problem, where we seek an actual subset of combinations that maximises m above) is at least as hard as this problem. (To see that the optimisation problem is not "much" harder than the decision problem, notice that you could first find the maximum m value for which a solution exists using a binary search on m in which you solve a decision problem at each step, and then, once this maximal m value has been found, solving a series of decision problems in which each combination in turn is removed: if the solution after removing some particular combination is still "YES", then it may also be left out of all future problem instances, while if the solution becomes "NO", then it is necessary to keep this combination in the solution.)
Given an instance (X, Y, Z, T, k) of 3DM, where X, Y and Z are sets that are pairwise disjoint from each other, T is a subset of X*Y*Z (i.e., a set of ordered triples with first, second and third components from X, Y and Z, respectively) and k is an integer, our task is to determine whether there is any subset U of T such that |U| >= k and all triples in U are pairwise disjoint (i.e., to answer the question, "Are there at least k non-overlapping triples in T?"). To turn any such instance of 3DM into an instance of your problem, all we need to do is create a fresh 4-combination from each triple in T, by adding a distinct dummy value to each. The set of objects in the constructed instance of your problem will consist of the union of X, Y, Z, and the |T| dummy values we created. Finally, set m to k.
Suppose that the answer to the original 3DM instance is "YES", i.e., there are at least k non-overlapping triples in T. Then each of the k triples in such a solution corresponds to a 4-combination in the input C to your problem, and no two of these 4-combinations overlap, since by construction, their 4th elements are all distinct, and by assumption of the. Thus there are at least m = k non-overlapping 4-combinations in the instance of your problem, so the solution for that problem must also be "YES".
In the other direction, suppose that the solution to the constructed instance of your problem is "YES", i.e., there are at least m non-overlapping 4-combinations in C. We can simply take the first 3 elements of each of the 4-combinations (throwing away the fourth) to produce a set of k = m non-overlapping triples in T, so the answer to the original 3DM instance must also be "YES".
We have shown that a YES-answer to one problem implies a YES-answer to the other, thus a NO-answer to one problem implies a NO-answer to the other. Thus the problems are equivalent. The instance of your problem can clearly be constructed in polynomial time and space. It follows that your problem is NP-hard.
You can reduce this problem to the maximum weighted clique problem, which is, unfortunately, NP-hard.
Build a graph such that every combination is a vertex with weight equal to the length of the combination, and connect vertices if the corresponding combinations do not share any object (i.e. if you can pick both them at the same time). Then, a solution is valid if and only if it is a clique in that graph.
A simple search on google brings up a lot of approximation algorithms for this problem, such as this one.
I'm self-learning with the edX course CS 188.1x Artificial Intelligence. Since the course concluded a year ago, it is in "archive mode" and there are no teaching staff to help with the questions. This also means I get no credit for finishing the course, so hopefully asking for help with a "homework" question here is okay.
In the first homework assignment the following question is asked:
Question 9: Hive Minds Lost at Night It is night and you control a single insect. You know the maze, but you do not know what square the
insect will start in. You must pose a search problem whose solution is
an all-purpose sequence of actions such that, after executing those
actions, the insect will be on the exit square, regardless of initial
position. The insect executes the actions mindlessly and does not know
whether its moves succeed: if it uses an action which would move it in
a blocked direction, it will stay where it is. For example, in the
maze below, moving right twice guarantees that the insect will be at
the exit regardless of its starting position.
It then asks the size of the state space. The answer is given as 2^MN, where M and N are the horizontal and vertical dimensions of the maze. Why is the answer the power set of MN? In my mind, the bug can only be in one square at the beginning, and we only have one bug, so I know the number of start states is MN. But the number of start states != state space, and that is where I am confused.
FYI - the cost per move is 1, and the bug can only move 1 square left, right, up, or down at a time. The goal is to get to the X (goal square).
Okay - I think I got it.
Set of all subsets (power set*) is exactly the right way to think about this. The state space is the set of all states.
1) Definition of state:
"A state contains all of the information necessary to predict the effects of an action and to
determine if it is a goal state." (http://artint.info/html/ArtInt_48.html)
The actions in this scenario are simple: left, right, up, down. They are the possible movements a bug could make.
2) Definition of solution:
Solutions are sequences of actions that lead to the goal test being
passed.
If we only permitted MN states, one for each possible starting position the bug was in, then we would have a state space that gave solutions that were valid only for discrete starting positions. But, the solution must be valid regardless of the initial state of the bug. This means the solution must work for scenarios in which the bug could occupy any of the MN available squares.
In other words, the solutions must be valid for each and every subset (combination) of possible starting spaces, which yields the power set of MN, which is 2^MN.
Why? Because solutions that are valid for a given start state may not be valid for all other start states. And the problem requires us to find solutions that are valid for all start states. This is also why the state space is much larger than MN even though in reality our bug only occupies 1 of the MN positions upon initialization. Just because a solution (sequence of moves) works when the bug starts at (1, 1) doesn't mean that solution (sequence of moves) will also work for the bug starting at (2, 1).
Bonus Question: Why isn't the state space just 1, the full set where
each of the MN squares 'has' a bug (and bugs are permitted to move
on top of each other)?
I was tempted to say that just because a sequence of moves gives a goal state when the bug can start at all of the MN possible positions, that doesn't mean that same sequence of moves gives a goal state when the bug starts at (3, 2) or at MN - 1 or MN - 2 etc. possible positions. But by definition it must (a solution over all starting points must be a solution over every finite subset of starting points).
So I think the reason you evaluate starting states other than "all boxes have a bug" is because the solution generated by evaluating only that state may not be optimal. And in fact this interpretation is borne out by what the homework gives as admissible heuristics for this problem:
The maximum of Manhattan distances to the goal from each possible
location the insect could be in.
OR
The minimum of Manhattan distances to the goal from each possible
location the insect could be in.
The case where we just have one starting state with bugs on all the boxes (with the magic ability to be on top of each other) is the relaxed problem we use to define our heuristic. Again by definition of admissibility, since the heuristic must not overestimate the true (arc) cost of an action, and since arc cost is given by Manhattan distances, both the heuristics above are admissible. (The maximum case is admissible because each possible location for the bug is, in fact, possible - thus the max cost is possible).
*If you don't know what power set means, all you need to know is that the power set is the set of all subsets of a given set. It is given by 2^(size of the set).
In other words, if I have a set of three balls {red, blue, green} and I want to know how many different subsets I have, I can calculate it as follows. A subset either has the element in it (1), or it doesn't (0). So {0, 0, 1} would be the subset of only the green ball, {1, 1, 1} would be the subset of all the balls (yes, technically this is a subset) and {0, 0, 0} would be the subset of none of the balls (again, technically a subset). So we see that the number of all subsets is 2^3 = 8. Or in our problem, 2^MN.
Suppose I have a a graph with 2^N - 1 nodes, numbered 1 to 2^N - 1. Node i "depends on" node j if all the bits in the binary representation of j that are 1, are also 1 in the binary representation of i. So, for instance, if N=3, then node 7 depends on all other nodes. Node 6 depends on nodes 4 and 2.
The problem is eliminating nodes. I can eliminate a node if no other nodes depend on it. No nodes depend on 7; so I can eliminate 7. After eliminating 7, I can eliminate 6, 5, and 3, etc. What I'd like is to find an efficient algorithm for listing all the possible unique elimination paths. (that is, 7-6-5 is the same as 7-5-6, so we only need to list one of the two). I have a dumb algorithm already, but I think there must be a better way.
I have three related questions:
Does this problem have a general name?
What's the best way to solve it?
Is there a general formula for the number of unique elimination paths?
Edit: I should note that a node cannot depend on itself, by definition.
Edit2: Let S = {s_1, s_2, s_3,...,s_m} be the set of all m valid elimination paths. s_i and s_j are "equivalent" (for my purposes) iff the two eliminations s_i and s_j would lead to the same graph after elimination. I suppose to be clearer I could say that what I want is the set of all unique graphs resulting from valid elimination steps.
Edit3: Note that elimination paths may be different lengths. For N=2, the 5 valid elimination paths are (),(3),(3,2),(3,1),(3,2,1). For N=3, there are 19 unique paths.
Edit4: Re: my application - the application is in statistics. Given N factors, there are 2^N - 1 possible terms in statistical model (see http://en.wikipedia.org/wiki/Analysis_of_variance#ANOVA_for_multiple_factors) that can contain the main effects (the factors alone) and various (2,3,... way) interactions between the factors. But an interaction can only be present in a model if all sub-interactions (or main effects) are present. For three factors a, b, and c, for example, the 3 way interaction a:b:c can only be in present if all the constituent two-way interactions (a:b, a:c, b:c) are present (and likewise for the two-ways). Thus, the model a + b + c + a:b + a:b:c would not be allowed. I'm looking for a quick way to generate all valid models.
It seems easier to think about this in terms of sets: you are looking for families of subsets of {1, ..., N} such that for each set in the family also all its subsets are present. Each such family is determined by the inclusion-wise maximal sets, which must be overlapping. Families of pairwise overlapping sets are called Sperner families. So you are looking for Sperner families, plus the union of all the subsets in the family. Possibly known algorithms for enumerating Sperner families or antichains in general are useful; without knowing what you actually want to do with them, it's hard to tell.
Thanks to #FalkHüffner's answer, I saw that what I wanted to do was equivalent to finding monotonic Boolean functions for N arguments. If you look at the figure on the Wikipedia page for Dedekind numbers (http://en.wikipedia.org/wiki/Dedekind_number) the figure expresses the problem graphically. There is an algorithm for generating monotonic Boolean functions (http://www.mathpages.com/home/kmath094.htm) and it is quite simple to construct.
For my purposes, I use the algorithm, then eliminate the first column and last row of the resulting binary arrays. Starting from the top row down, each row has a 1 in the ith column if one can eliminate the ith node.
Thanks!
You can build a "heap", in which at depth X are all the nodes with X zeros in their binary representation.
Then, starting from the bottom layer, connect each item to a random parent at the layer above, until you get a single-component graph.
Note that this graph is a tree, i.e., each node except for the root has exactly one parent.
Then, traverse the tree (starting from the root) and count the total number of paths in it.
UPDATE:
The method above is bad, because you cannot just pick a random parent for a given item - you have a limited number of items from which you can pick a "legal" parent... But I'm leaving this method here for other people to give their opinion (perhaps it is not "that bad").
In any case, why don't you take your graph, extract a spanning-tree (you can use Prim algorithm or Kruskal algorithm for finding a minimal-spanning-tree), and then count the number of paths in it?
Firstly, I apologize for the poor title; I cannot think of a good name for this algorithm.
I have an ordered list of stages. Each stage has a cast of characters, unordered. Characters can occur in multiple stages.
A crossing occurs when two consecutive stages cannot have their casts concatenated, with overlap allowed where it would unify the same character on both casts, in a way that leaves a character duplicated in the concatenation. Or, informally, a crossing is when a character would need to be at two different spots at once in a line-up of the combined casts. In code:
uncrossed = [D, F], [N, V, S]
overlap = [D, F, V], [V, N, S]
crossed = [D, V, F], [N, V, S]
In the first example, V isn't with D and F, so there aren't any crossings. In the second example, V is with D and F and then with N and S, but this isn't a problem because the ordering permits (with overlap) a crossing-less concatenation. On the third example, though, the ordering forces a crossing.
For my purposes, crossings can occur on non-consecutive stages as if characters did not actually stray from their previous order in the cast when they are not "on-stage."
I would like to order each stage's cast such that there are as few crossings as possible, understanding that it is definitely possible to have situations where crossings are inevitable. An example series which requires crossings:
required = [A, B], [B, C], [A, C], [A, B]
This all sounds very abstract and silly, so I'll provide a concrete example of a human solving this algorithm for a purpose similar to mine: http://xkcd.com/657/ In this case, the constraint is deliberately ignored for aesthetic purposes, but it's still possible to get a visual idea of what I'm talking about.
I already have some crude ideas for how to solve this, but nothing affordable, and I'm wondering if this is isomorphic to some problem already covered in the literature. It sounds vaguely topological as well.
Since people asked, this algorithm appears to be key to automatically generating pretty timelines for storyboards of characters in stories, and that's what I'm intending to use it for.
This isn't an answer, but I think maybe a more precise or even more correct formulation of what you are looking for:
There is a set, call it C, of characters, and there is a finite ordered sequence S_1, ... S_n of scenes, where a scene is a set consisting of some of the characters. Characters may (and typically do) appear in multiple scenes.
I'd like to phrase your desired outcome in a slightly different way from how you phrased it, because I think it makes it clearer how one may search for a solution (or at least, it makes it totally clear how to brute-force a solution):
The output of our algorithm is a sequence of arrangements of the characters. An arrangement of the characters is just a permutation of the ordered tuple [c_1, ... c_m], where the c_i are the characters, and there are m of them in total, so C = {c_1, ..., c_m}. We want n arrangements in total, call them A_1, ..., A_n, one per scene.
What arrangement A_n corresponds to is the top-to-bottom ordering of the characters in your storyboard, during scene n, in the following sense: draw a vertical line through your storyboard passing through scene n. This line should hit the characters' life-lines in the order specified by A_n.
We require the following property of our arrangements: given scene S_n, the arrangement A_n needs to put the characters contained in S_n into a contiguous chunk, in the following sense: suppose that S_n = {c_2, c_3, c_5}. Then A_n may yield [c_1, c_4, c_2, c_3, c_5], but may not yield [c_2, c_1, c_3, c_4, c_5]. This is because you don't want an errant character "cutting through" the scene in the storyboard.
We hope to minimize the number of "crossings." Here, crossings are easy to define: the number of crossings between A_i and A_(i+1) is exactly equal to the number of transpositions of adjacent characters required to go from permutation A_i to permutation A_(i+1).
I haven't given you an answer, but I think that given the above setup, a brute-force approach isn't too hard to code up, and will give you an answer overnight without a problem, if the storyboard isn't too big.
I think that if you posted this problem on MathOverflow, you could possibly get someone interested in it. Or maybe it has been solved, who knows?
Lets say I have a parabola. Now I also have a bunch of sticks that are all of the same width (yes my drawing skills are amazing!). How can I stack these sticks within the parabola such that I am minimizing the space it uses as much as possible? I believe that this falls under the category of Knapsack problems, but this Wikipedia page doesn't appear to bring me closer to a real world solution. Is this a NP-Hard problem?
In this problem we are trying to minimize the amount of area consumed (eg: Integral), which includes vertical area.
I cooked up a solution in JavaScript using processing.js and HTML5 canvas.
This project should be a good starting point if you want to create your own solution. I added two algorithms. One that sorts the input blocks from largest to smallest and another that shuffles the list randomly. Each item is then attempted to be placed in the bucket starting from the bottom (smallest bucket) and moving up until it has enough space to fit.
Depending on the type of input the sort algorithm can give good results in O(n^2). Here's an example of the sorted output.
Here's the insert in order algorithm.
function solve(buckets, input) {
var buckets_length = buckets.length,
results = [];
for (var b = 0; b < buckets_length; b++) {
results[b] = [];
}
input.sort(function(a, b) {return b - a});
input.forEach(function(blockSize) {
var b = buckets_length - 1;
while (b > 0) {
if (blockSize <= buckets[b]) {
results[b].push(blockSize);
buckets[b] -= blockSize;
break;
}
b--;
}
});
return results;
}
Project on github - https://github.com/gradbot/Parabolic-Knapsack
It's a public repo so feel free to branch and add other algorithms. I'll probably add more in the future as it's an interesting problem.
Simplifying
First I want to simplify the problem, to do that:
I switch the axes and add them to each other, this results in x2 growth
I assume it is parabola on a closed interval [a, b], where a = 0 and for this example b = 3
Lets say you are given b (second part of interval) and w (width of a segment), then you can find total number of segments by n=Floor[b/w]. In this case there exists a trivial case to maximize Riemann sum and function to get i'th segment height is: f(b-(b*i)/(n+1))). Actually it is an assumption and I'm not 100% sure.
Max'ed example for 17 segments on closed interval [0, 3] for function Sqrt[x] real values:
And the segment heights function in this case is Re[Sqrt[3-3*Range[1,17]/18]], and values are:
Exact form:
{Sqrt[17/6], 2 Sqrt[2/3], Sqrt[5/2],
Sqrt[7/3], Sqrt[13/6], Sqrt[2],
Sqrt[11/6], Sqrt[5/3], Sqrt[3/2],
2/Sqrt[3], Sqrt[7/6], 1, Sqrt[5/6],
Sqrt[2/3], 1/Sqrt[2], 1/Sqrt[3],
1/Sqrt[6]}
Approximated form:
{1.6832508230603465,
1.632993161855452, 1.5811388300841898, 1.5275252316519468, 1.4719601443879744, 1.4142135623730951, 1.35400640077266, 1.2909944487358056, 1.224744871391589, 1.1547005383792517, 1.0801234497346435, 1, 0.9128709291752769, 0.816496580927726, 0.7071067811865475, 0.5773502691896258, 0.4082482904638631}
What you have archived is a Bin-Packing problem, with partially filled bin.
Finding b
If b is unknown or our task is to find smallest possible b under what all sticks form the initial bunch fit. Then we can limit at least b values to:
lower limit : if sum of segment heights = sum of stick heights
upper limit : number of segments = number of sticks longest stick < longest segment height
One of the simplest way to find b is to take a pivot at (higher limit-lower limit)/2 find if solution exists. Then it becomes new higher or lower limit and you repeat the process until required precision is met.
When you are looking for b you do not need exact result, but suboptimal and it would be much faster if you use efficient algorithm to find relatively close pivot point to actual b.
For example:
sort the stick by length: largest to smallest
start 'putting largest items' into first bin thy fit
This is equivalent to having multiple knapsacks (assuming these blocks are the same 'height', this means there's one knapsack for each 'line'), and is thus an instance of the bin packing problem.
See http://en.wikipedia.org/wiki/Bin_packing
How can I stack these sticks within the parabola such that I am minimizing the (vertical) space it uses as much as possible?
Just deal with it like any other Bin Packing problem. I'd throw meta-heuristics on it (such as tabu search, simulated annealing, ...) since those algorithms aren't problem specific.
For example, if I'd start from my Cloud Balance problem (= a form of Bin Packing) in Drools Planner. If all the sticks have the same height and there's no vertical space between 2 sticks on top of each other, there's not much I'd have to change:
Rename Computer to ParabolicRow. Remove it's properties (cpu, memory, bandwith). Give it a unique level (where 0 is the lowest row). Create a number of ParabolicRows.
Rename Process to Stick
Rename ProcessAssignement to StickAssignment
Rewrite the hard constraints so it checks if there's enough room for the sum of all Sticks assigned to a ParabolicRow.
Rewrite the soft constraints to minimize the highest level of all ParabolicRows.
I'm very sure it is equivalent to bin-packing:
informal reduction
Be x the width of the widest row, make the bins 2x big and create for every row a placeholder element which is 2x-rowWidth big. So two placeholder elements cannot be packed into one bin.
To reduce bin-packing on parabolic knapsack you just create placeholder elements for all rows that are bigger than the needed binsize with size width-binsize. Furthermore add placeholders for all rows that are smaller than binsize which fill the whole row.
This would obviously mean your problem is NP-hard.
For other ideas look here maybe: http://en.wikipedia.org/wiki/Cutting_stock_problem
Most likely this is the 1-0 Knapsack or a bin-packing problem. This is a NP hard problem and most likely this problem I don't understand and I can't explain to you but you can optimize with greedy algorithms. Here is a useful article about it http://www.developerfusion.com/article/5540/bin-packing that I use to make my php class bin-packing at phpclasses.org.
Props to those who mentioned the fact that the levels could be at varying heights (ex: assuming the sticks are 1 'thick' level 1 goes from 0.1 unit to 1.1 units, or it could go from 0.2 to 1.2 units instead)
You could of course expand the "multiple bin packing" methodology and test arbitrarily small increments. (Ex: run the multiple binpacking methodology with levels starting at 0.0, 0.1, 0.2, ... 0.9) and then choose the best result, but it seems like you would get stuck calulating for an infinite amount of time unless you had some methodlogy to verify that you had gotten it 'right' (or more precisely, that you had all the 'rows' correct as to what they contained, at which point you could shift them down until they met the edge of the parabola)
Also, the OP did not specify that the sticks had to be laid horizontally - although perhaps the OP implied it with those sweet drawings.
I have no idea how to optimally solve such an issue, but i bet there are certain cases where you could randomly place sticks and then test if they are 'inside' the parabola, and it would beat out any of the methodologies relying only on horizontal rows.
(Consider the case of a narrow parabola that we are trying to fill with 1 long stick.)
I say just throw them all in there and shake them ;)