Permutations in Excel - excel

I am have a string with 6 spaces, e.g. 000000. Each space can hold one of three digits - 0, 1, or 2. I know that I can get a total of 120 permutations using the Permut function in Excel, i.e. =PERMUT(6,3) = 120. But I would actually like to have each individual permutation in a cell, e.g. 000001, 000010, etc.. Ideally, the end result would be 120 rows of unique 6-digit IDs.
Please help if you know a faster way of accomplishing this without entering the figures manually.
Thanks!

There is a VBA functionin the last post on this page. Copy it into a VBA module, then in Excel, create a column of integers from 0 to n where n = the number of IDs you want. In the next column, call the VBA function with the value from the first column as the first argument, and 3 as the second argument. Something like
Column A Column b
0 =baseconv(A1, 3)
1 =baseconv(A2, 3)
2 =baseconv(A3, 3)
... etc.
Your IDs are really just incremental values using a base 3 counting system. You can format the output to get leading zeros with a custom format of '000000'.
Incidentally, with 6 positions and 3 available values, you can get 3 ^ 6, or 729 unique IDs

First, I don't think you're using PERMUT correctly here. What PERMUT(6,3) gives you is the total number of ways to arrange three things picked out of a set of six things. So the result is 120 because you could have 6*5*4 possible permutations. In your case you have 3^6 = 729 possible strings, because each position has one of three possible characters.
Others have posted perfectly fine VBA-based solutions, but this isn't that hard to do in the worksheet. Here is an array formula that will return an array of the last six digits of the ternary (base-3) representation of a number:
=FLOOR(MOD(<the number>,3^({5,4,3,2,1,0}+1))/(3^{5,4,3,2,1,0}),1)
(As WarrenG points out, just getting a bunch of base-3 numbers is one way to solve your problem.)
You would drag out the numbers 0 through 728 in a column somewhere, say $A$1:$A$729. Then in $B$1:$G$1, put the formula:
=FLOOR(MOD(A1,3^({5,4,3,2,1,0}+1))/(3^{5,4,3,2,1,0}),1)
remembering to enter it as an array formula with Ctrl-Shift-Enter. Then drag that down through $B$729:$G$729.
Finally in cell $H$1, put the formula:
=CONCATENATE(B1,C1,D1,E1,F1,G1)
and drag that down through $H$729. You're done!

Related

In Excel how can I convert a list of numbers (e.g. 1, 3, 7) in one cell to dummy variables (1s) in adjacent cells?

I have been given an Excel spreadsheet with columns extracted from an online survey that contain lists of integers for options that participants have ticked. E.g. one participant may have ticked options 1, 6 and 11 in the survey so the cell contains [1,6,11]. Another just option 2. The range of possible values is from 1 to 11 in some cases, and 1 to 18 in other cases.
I need to transform these lists into 18 adjacent columns that contain a 1 if that column's number was present and 0 if it was not. Doing this manually would be extremely tedious and error prone.
The 11 or 18 adjacent columns already exist in the Excel spreadsheet.
I have tried using, for example:
=IFERROR(IF(FIND("2",A1), 1, 0), 0)
to place a "1" in the Option2 column if 2 is present in the list, and 0 if it is not.
This partially works but there are issues with the ambiguity of "1", "1,11" and "11".
I would appreciate thoughts on how best to achieve this.
The following image shows example of the desired result, but done manually...
You need to wrap the number you are checking for, and the string you are looking in, in commas (,) to avoid ambiguity.
There are several ways of producing a 1 for a match - my personal preference is to use Isnumber to see if the match is true or false, then the double unary minus to convert the result to a one or a zero:
=--ISNUMBER(FIND(","&COLUMN(A1)&",",","&$A2&","))

SUMIF: formula as criteria not working for entire column

My worksheet contains orders from clients. The orders are all wooden panels.
Every order is assigned a number which is led by the letter Q.
Column B contains the number of parts in the order.
Column C contains the total m² in the order.
Orders that contain one or more parts that are 2.8 x 0.0735 m will get a row of their own.
I'm trying to count the number of times that this part occurs in a list of more than a thousand rows.
So if I divide the total m² by the m² of the part I'm looking for and divide this by the amount of parts in the order, I should get exactly 1 as a result.
If I take the sum of all the number of parts that result in a 1, I get my total.
Now I'd like to put this in one formula for the entire worksheet, but SUMIF doesn't work the way I'm trying. (It's in Dutch)
=SOM.ALS(B:B;(C:C/(2,8*0,0735)/B:B)=1)
I can't seem to use this formula as a criterium in the SUMIF.
For now I use a helping column that gives the right amount per row. Then take the total SUM of these.
Is it possible to put this in a single formula?
Yes, it is possible. Try this one:
{=SUM(--(B:B=C:C/(2.8*0.0735))*IF(ISERROR(1/B:B),0,1))}
Remember to enter it as an array function with CNTRL + SHIFT + ENTER.
The first half of the formula is just a logical test, after the asterisk it tests if 1/B results in an error (thereby omitting text, zeroes, and blanks) and returns a zero if there is an error.
These are then summed and the result displayed.
In Dutch and English:
{=SOMPRODUCT(--(B:B=(ALS(ISTEKST(C:C);1;C:C))/(2,8*0,0735));B:B)}
{=SUMPRODUCT(--(B:B=(IF(ISTEXT(C:C),1,C:C))/(2.8*0.0735)),B:B)}
is working perfectly. (Enter with Ctrl-Shift-Enter)
The first bit is the logical test, which will check if B:B = C:C / (2.8*0.0735)
It got stuck on #VALUE! because there is text in C:C.
The IF(ISTEXT)) eliminates text by converting them to numeric values, in this case 1, but it can be any numeric value.
The logical test will return TRUE(1) or FALSE(0) because of the double dash or unary operator and this will be multiplied by their respective B:B value.
Because the row with text has no value in B:B, it will result as zero.

Excel shows name twice

I got a problem with my Excel, where it shows a same name twice, if the 'racers' have the excact same time. For example in the picture the racers 7 & 9 and racers 5 & 10 have the same time, but in the Start grid it shows the same name twice. It should be 4. Racer7 5. Racer9 & 9. Racer5 10. Racer10
The Function of Cell I3 =IF(OR(ISBLANK(B3);ISBLANK(C3));"";INDEX($B$3:$B$32;MATCH(J3;$D$3:$D$32;0))) (I have to use format ';' instead of ',') Function of cell J3 =IFERROR(SMALL($D$3:$D$32;H3);"")
Link to the file (does not work in Google Sheets & the functions have to use local formatting)
xlsx file
MATCH and RANK Getting Sick When Handling Time
Formulas
COMMA
[D3] =IF(NOT(ISNUMBER(C3)),"",ROUND($D$1-A3*"00:10,0"-C3,8))
[H3] =IF(ISNUMBER(K3),RANK(J3,D$3:D$32,2),"")
[I3] =IF(IFERROR(INDEX($B$3:$B$32,SMALL(IF($D$3:$D$32=J3,ROW($J$3:$J$32)-ROW(J$3)+1),COUNTIF($J$3:$J3,J3))),"")=0,"",IFERROR(INDEX($B$3:$B$32,SMALL(IF($D$3:$D$32=J3,ROW($J$3:$J$32)-ROW(J$3)+1),COUNTIF($J$3:$J3,J3))),""))
[J3] =IFERROR(SMALL($D$3:$D$32,A3),"")
[K3] =IFERROR(J3-J$3,IF(I3="","","disqualified"))
COLON
[D3] =IF(NOT(ISNUMBER(C3));"";ROUND($D$1-A3*"00:10;0"-C3;8))
[H3] =IF(ISNUMBER(K3);RANK(J3;D$3:D$32;2);"")
[I3] =IF(IFERROR(INDEX($B$3:$B$32;SMALL(IF($D$3:$D$32=J3;ROW($J$3:$J$32)-ROW(J$3)+1);COUNTIF($J$3:$J3;J3)));"")=0;"";IFERROR(INDEX($B$3:$B$32;SMALL(IF($D$3:$D$32=J3;ROW($J$3:$J$32)-ROW(J$3)+1);COUNTIF($J$3:$J3;J3)));""))
[J3] =IFERROR(SMALL($D$3:$D$32;A3);"")
[K3] =IFERROR(J3-J$3;IF(I3="";"";"disqualified"))
Why is MATCH 'miscalculating' to '7' instead of '6' in cells 'I6' and 'I7' in OP's worksheet (formula in 'D3')?
Time has a ton of decimals so I guess it's 'seeing' the values in 'D8' and 'D9' as different values. To avoid this you can round the values. If you want to use only these values it is enough to round them to 8 decimals for the numbers to be recognized as different even by a millisecond. If you want to sum them there might be some inaccuracies. In OP's case 8 decimals is more than enough.
RANK (formula in 'H3') is also 'miscalculating' if no rounding.
Why the long formula?
Best try it with and without the IF statement and see for yourself.
Here's a Hint:
For this you need a tie breaker. The unfortunately best way of doing this is using a helper column. In my test sheet I used column E but the column could, of course, be anywhere. More importantly, it could be hidden. In this column you enter a formula like
=D3+ROW()/10^8
The point is that the addition must be so small that it makes no difference to the result on rounding. So, the number of results you treat in this may makes a difference. If you find that the addition changes the result in the last row, increase the exponent. The change I made add 0.0001 seconds to each result, multiplied by the row number: 0.0001 in the first row, 0.0002 in the second, 0.0003 in the third etc. Check the results in the 10th and 100th row.
Now the results in column E are all different and it's these results that are used in columns J and I.
[J3] =SMALL($E$3:$E$32,H3)
and
[I3] =INDEX($B$3:$B$32,MATCH(J3,$E$3:$E$32,0))
There will be no more duplicates but the "winner" of a draw is decided by his position in the list.
A solution in old school array-formula-style would be:
Note It's an array-formula which needs to be confirmed through CTRLSHIFTENTER
=IF(OR(ISBLANK(B3),ISBLANK(C3)),"",INDEX($B$1:$B$32,SMALL(IF($D$1:$D$12=J3,ROW($J$1:$J$12)),COUNTIF($J$1:$J3,J3))))
The IF checks the timelist for the current time value and gives all matching lines back which are getting ranked by small. COUNTIF counts the occurences of the current time up to the current line.

Find the nearest number greater than a specific value among cells

I have 3 different cells like this in my Excel table:
[B1] = 2
[N50] = 5
[V25] = 10
I want to find in those cells the nearest number greater than a specific value. For example, if the value is 1 then the number should be 2 in cell [B1]. If the value is 4 then the number should be 5 in cell [N50].
=IF(A2<LARGE(CHOOSE({1,2,3},D2,F3,H1),1),
IF(A2<LARGE(CHOOSE({1,2,3},D2,F3,H1),2),
IF(A2<LARGE(CHOOSE({1,2,3},D2,F3,H1),3),
LARGE(CHOOSE({1,2,3},D2,F3,H1),3),
LARGE(CHOOSE({1,2,3},D2,F3,H1),2)),
LARGE(CHOOSE({1,2,3},D2,F3,H1),1)),
"larger or equal to all searched numbers")
and in one nice straight line for copy and paste purposes:
=IF(A2<LARGE(CHOOSE({1,2,3},D2,F3,H1),1), IF(A2<LARGE(CHOOSE({1,2,3},D2,F3,H1),2), IF(A2<LARGE(CHOOSE({1,2,3},D2,F3,H1),3), LARGE(CHOOSE({1,2,3},D2,F3,H1),3), LARGE(CHOOSE({1,2,3},D2,F3,H1),2)), LARGE(CHOOSE({1,2,3},D2,F3,H1),1)), "larger or equal to all searched numbers")
The hardest part for me and I did not understand it and still do not...just accepting, is building your separate cells into an array. That part is done by the CHOOSE():
CHOOSE({1,2,3},D2,F3,H1)
Once it is in an array, perform a large function to sort it from largest to smallest. Then through a series of nested IF statements, checked to see if the specified number in A2 was smaller than the K largest number.
Here is a proof of concept scaled down to smaller range but give you the idea.
Now I did it with a large, you could have done it with a small function as well, you would just need to alter your logic in the if statements.
This is an alternative approach without the if statements:
=IF(A2>=MAX(A7,C8,E6),"Greater than or equal to all options",INDEX(CHOOSE({1,2,3},A7,C8,E6),IFERROR(MATCH(A2,CHOOSE({1,2,3},A7,C8,E6),1)+1,1)))

Excel - Return the first negative number of a column

I'm using Excel 2010 and I'm looking for a way to return the first negative number of a column. For instance, I have the following numbers distributed in a column:
1
4
6
-3
4
-1
-10
8
Which function could I use to return -3?
Thanks!
This could be interpreted two ways... If all the numbers are in a single cell (one column) as a string, the MID function can be used. If the numbers are in A1, a formula that could work is this:
=VALUE(MID(A1,SEARCH("-",A1),SEARCH(" ",A1,SEARCH("-",A1))-SEARCH("-",A1)))
If the numbers are each in their own columns (in my example, A3:H3), a different technique must be used:
{=INDEX(A3:H3,1,MATCH(TRUE,A3:H3<0,0))}
Don't type the { } - enter the equation using CTRL+SHIFT+ENTER.
In each case, the formula will return the number -3, which is the first negative number in the series.
Another possibility, avoiding the array formula (which are a big source of performance issues):
=LOOKUP(1;1/(M2:M15<0);M2:M15)
(I assume your numbers are in the M2:M15 range).
This will return the first number matching the "<0" condition. You may use any other condition, including text comparisons.
You may also extract the value of another array corresponding to the matching cell:
=LOOKUP(1;1/(M2:M15<>"OK");T2:T15)
In this example, the first cell containing another string than "OK" will be searched for in the m2:m15 array and the corresponding value in array t2:t15 will be returned.
Please note that the usage of the lookup function should be avoided whenever possible (but in this case, it's very handy !)
(I got the original inspiration for this answer from this post)

Resources