Aligning LSB of two arrays into columns in C - c

I have two arrays of decimals with the same number of indexes in each. How can I right-align the LSB in each column like this?:
359230595 10
1746442051 8
1170647010 8
202212421 7
800051251 7
1112147574 8
1135948848 8
3367006 5
3869426816 7
Either using printf, or even better would be getting each line into a string array so I can output it to another .txt file more easily.

I feel confident that this has been asked and answered before. To make it easy on you, however...
printf has an alignment operation that you can use. You can find it if you read the manual page. For example:
printf("%*d %*d\n", 10, x, 10, y);
Note that the * has been inserted where you would typically find a precision marker. The * is used as a placeholder for you to indicate the maximum length for that field. In this case, this will produce two right-aligned columns 10 spaces in width, separated by one space.

Related

(arrays) how to move a range of elements to another position

i have a dynamic html table, generated with php, with data from mariadb
i need an algorithm (preferently in sql, or in php if not) to re-order the rows and submit... like this (where x = checkbox, o = radiobutton):
range dest data
---------------
. . one
x . two
x o three
x . four
. . five
[submit move]
the idea is similar to excel> select rows> move+insert rows... first you select a source RANGE (i did with js, just select first, last, and the range selects itself), then you select an insert destination position, then submit... in this example the result will be
one
five
two
three
four
as you can see the selected range [two..four] has advanced to specified position, shifting the overwriten items to space left by the range, preserving the length but just changing indexes... i imagine some sql commands like
UPDATE my_table SET index=index+$diff WHERE index>=$start AND index<=$end;
seems easy but is not so much (for me at least) since there are many different cases with different range lenghts, positions, etc... i couldn't found any native sql or php function or snippet to do it
please if you have some knowledge or idea about some related algorithm i will be very thankful ... and forgive my bad english xD
due the question popularity xD i tried to find an answer myself... and share it with the hope will be useful to somebody, and hopufully motivate someone else to find a better solution
consider this initial set of elements (only indexes shown), and that we want to move elements from 2 to 4 to position 6... we expect a final result
orig 1 2 3 4 5 6 7 8 9
src 2 3 4
dest 6
final 1 5 6 7 8 2 3 4 9
first thing i did was to calculate the source range length, that is 4 -2 = 2
then saved the source range in a temp table, or by marking elements someway, or by writing down unique id's, etc...
until the indexes could simply be duplicated, imagine instead we take away the source range and left a "hole" of "length +1" elements in the list
2 3 4
^ ^ ^
1 . . . 5 6 7 8 9
then the key is to shift the remaining elements to the opposite side "length +1" positions, can be done by substracting "length" to remaining elements
< < <
1 5 6 7 8 . . . 9
take note the remaining items you shifted is 4, this is the difference between after the last source element and the last destination position... the last destination position is destination + "length" (6 +2 = 8)
in the case the movement is done to the opposite direction (i.e. the source range to their left) all ranges, shifts and operations must be corrected acordingly
now you can set source range to his new position by simply correcting the indices adding "remaining length" (4) to indexes
> > > > 2 3 4
1 5 6 7 8 . . . 9
be aware destination position can't go outside (first) and (last -"length") positions, i.e. (1 and 7) for this case... and if first source index equals destination the list wouldn't change
so to conclude, there 3 cases with slightly different operations:
move the source range to their right
move it to same position (do nothing)
move it to left
now you could post a pseudocode snippet below as a complement :) ... thanks

Convert big number to single digit array

So, I need to convert any number to its reverse and put it in an array.
For example:
123456789 --> [9 8 7 6 5 4 3 2 1]
I managed to do it for small numbers like the example with this:
n=32134654654213
rev=(fliplr(num2str(n)));
mikos=length(rev);
array=[ ]
for i=1:mikos
array=[array,str2num(rev(i))]
end
But when I put a big number like 564465426464334345413435541 the array is always 1x18 double and does not show all the digits.
Any ideas?
edit As you tell me in comments, it is a limit of how many digits a double can hold. You are right, if I use a string input, it works as a charm. Still wondering hot to make it work as a function, with this form :
function digits = GetDigits(n)
As mentioned in the comments, you have a limit on the number of digits a double can store. The limit on a uint64 is bigger (19), but still not sufficient to store your value. I would make sure it does not happen.
function digits = GetDigits(n)
%check if the value behaves as a normal integer
if isnumeric(n)
if n==(n+1),error('n too big, supply as string instead');end
end
rev=(fliplr(num2str(n)));
mikos=length(rev);
array=[ ]
for i=1:mikos
array=[array,str2num(rev(i))]
end
end

Using an Array to get the average of a selection of numbers

I have 12 different numbers on a row in an excel sheet (repeated few times on different row) and I would like to get the average of the 8 bigger numbers (4 numbers won't be used). I thought to use an array, but how to select the 8 bigger numbers in this array?
I would like to do it in VBA. Do you have any ideas/directions how to proceed, because I am not really sure how to start.
Example: 12,3,5,6,8,11,9,7,5,8,10,1 (Results=8.875), if I didn't make a mistake!
Thanks.
I know you asked for VBA, but here's a formula. If this works, you can quickly throw in VBA (use the macro recorder to see how if you're unsure).
If that's in row 1, you can use:
=AVERAGE(LARGE(A1:L1,{1,2,3,4,5,6,7,8}))
You should be able to change A1:l1 to be the range where your numbers are, i.e.
=AVERAGE(LARGE(A1:F2,{1,2,3,4,5,6,7,8}))
Edit: Per your comment, also no need for VBA. Just use conditional highlighting. Highlight your range of numbers, then go to Conditional Highlighting --> Top/Bottom Rules --> Top 10 Items. Then just change the 10 to 8, and choose a color/format. Then Apply!
(each row in the above is treated as it's own range).
Edt2: bah, my image has duplicate numbers which is why the top 8 rule is highlighting 9 numbers sometimes. If you request I'll try to edit and tweak
You can use a simple Excel function to compute the answer
=AVERAGE(LARGE(A1:L1, {1,2,3,4,5,6,7,8}))
It is a bit more complex in VBA, but here is a function that does the same computation (explicit typing per Mat's Mug):
Public Function AvgTop8(r As Range) As Double
Dim Sum As Double, j1 As Integer
For j1 = 1 To 12
If WorksheetFunction.Rank(r(1, j1), r) <= 8 Then
Sum = Sum + r(1, j1)
End If
Next j1
AvgTop8 = Sum / 8#
End Function
The Excel RANK function returns the rank of a number in a list of numbers, with the largest rank 1 and so on. So you can search through the 12 numbers for the 8 largest, sum them and divide by 8.
You don't need VBA for this. You can use:
=AVERAGE(LARGE(A1:L1,{1;2;3;4;5;6;7;8}))

Excel: How to check for repeated numbers inside a cell

I have an excel spreadsheet with numbers from 000 to 999 and am trying to find repeated numbers inside a cell.
(So for example, printing 1 if the number is 022 , 555 or 115 and 0 if it isn't)
So far, I have not been able to find a solution.
Feel free to ask for more information and thanks in advance.
This will do: =IF(COUNT(SEARCH(REPT({0,1,2,3,4,5,6,7,8,9},2),A1))>0,1,0)
Note: If value in cell A1 contains 2 repeated digits it will show 1 else 0. You can customize the repetition limit by changing 2 in the part 8,9},2).
You could try this one if you wanted to find repeated digits not necessarily next to each other:-
=IF(MAX(LEN(A1)-LEN(SUBSTITUTE(A1,{0,1,2,3,4,5,6,7,8,9},"")))>1,1,0)
If the numbers are stored as 3-digit numbers and you wanted it to work for (e.g.) 001, would need:-
=IF(MAX(LEN(TEXT($A1,"000"))-LEN(SUBSTITUTE(TEXT($A1,"000"),{0,1,2,3,4,5,6,7,8,9},"")))>1,1,0)
If your data is in Range "A1:A100" and you want to locate repeated numbers in the range for instance, enter =IF(COUNTIF(A:A,A1)>1,1,0) in cell B1 and fill down. But if you want to check repetitions of specific numbers like 022, 555 or 115, enter =IF(OR(AND(A1=022,COUNTIF(A:A,A1)>1),AND(A1=555,COUNTIF(A:A,A1)>1),AND(A1=115,COUNTIF(A:A,A1)>1)),1,0) in cell B1 and fill down.
being a number, use arithmetics to break it into digits and then check if all are different.
the formula is
=INT(NOT(AND(INT(A1/100)<>INT(MOD(A1,100)/10),INT(A1/100)<>MOD(A1,10),INT(MOD(A1,100)/10)<>MOD(A1,10))))
let's analyze it step by step
first, INT(A1/100) extracts the first digit (the integer division by 100); then INT(MOD(A1,100)/10) extracts the second digit (the integer division by 10 of the modulo 100); and MOD(A1,10) extracts the last digit (the modulo 10).
next there are the three comparisons of difference <> first with second, second with third and first with third, combined with AND() and finally take the result, negate it NOT() and transforming it into an integer 0 or 1 with INT()

Using binary strings on storing ordered items in database

In this post, #boisvert mentioned that if using string as the order field's value, it is best shown for a binary string, and then gave an algorithm to calculate the average of two binary strings as follows:
Avalue = 1+0*(1/2)+1*(1/4)+1*(1/8)
Bvalue = 1+1*(1/2)+0*(1/4)+0*(1/8)
average, new value = 1+0*(1/2)+1*(1/4)+1*(1/8)+1*(1/16) new string = "10111"
content order
--------------------
A '1011'
new! '10111'
B '1100'
C '1101'
I couldn't understand these very well, what's the value of the first item putting into the DB and the items inserting before/after it? How to calculate the average between '1011' and the new value '10111', or between '111' and '1000'?
Any help is much appreciated.
The binary strings are fractions, not integers; the decimal point is always at the beginning (or after the first digit, in #boisvert's answer; it doesn't make any difference as long as the position of the decimal point is fixed. Of course, it's actually a binary point since these are binary numbers.)
To find the average:
If the strings differ in length, put enough 0s at the end of the shorter string so that it is the same length as the longer string.
Add the two strings together, using binary addition, always putting the last carry at the beginning, even if it is ยด0'. [See algorithm below].
Remove any 0s at the end.
Example 1: 1011 and 10111
Extend the first string with a 0: 10110 and 10111
Find the sum:
A: 10110
B: 10111
Carry: 101100
Sum: 101101
No trailing zeros, so the result is 101101
Example 2: 111 and 1000
1. 1110 1000
2. 10110
3. 1011
Starting off and insertion at the end:
The first item put into the database has the label 1. If at any point you need to add an item at the very beginning, use the first label with a 0 before it. Similarly, if you need to add an item at the end, use the first label with a 1 before it.
Binary addition:
Since the strings are the same length, this is easy; set Carry to 0, and scan both strings from back to front. (The output is also produced back-to-front.)
At each position:
* If the sum of Carry and the two digits is 1 or 3, output a 1, otherwise output a 0.
* If the sum of Carry and the two digits is 2 or 3, set Carry to 1, otherwise set it to 0.
When you've finished all the digits, output the value of Carry.
Practical implementation:
In practice, you wouldn't use binary strings; you'd use some fairly large base, the only requirement being that it is even. But the algorithms are the same. When constructing the representation of your numbers, you need to assign digits to characters in alphabetical order, so that the resulting strings can be sorted alphabetically without converting them to numbers; the database doesn't know how to convert to numbers, but it knows how to sort strings alphabetically.

Resources