Replace Square-Expression in Maple - symbolic-math

Given a maple expression like
f := (y + 5)^2 + x^2
How can I replace all occurrences of the square function with a custom function? The result I want to have would be
square(y + 5) + square(x)
I tried something like
subs({x^2 = square(x)}, f)
However, that only replaces the x^2 expression. I could of course list explicitly the (y + 5) term as well, but I want to replace any occurrence of (.)^2 without listing everything explicitly.
How can I do this in Maple?

You can accomplish this using either subsindets or applyrule.
expression:=(y-5)^2+3+sin(((z-1/3)^2/(t-(y-s)^2)))+F(f(17+p^2)^2);
/ 2 \
| / 1\ |
| |z - -| | / 2\
2 | \ 3/ | | / 2 \ |
expression := (y - 5) + 3 + sin|------------| + F\f\p + 17/ /
| 2|
\t - (y - s) /
applyrule(_a::anything^2=square(_a), expression);
/ / 1\ \
| square|z - -| |
| \ 3/ |
square(y - 5) + 3 + sin|-----------------| + F(square(f(square(p) + 17)))
\t - square(y - s)/
subsindets(expression, '`^`'(anything,2), u->square(op(1,u)));
/ / 1\ \
| square|z - -| |
| \ 3/ |
square(y - 5) + 3 + sin|-----------------| + F(square(f(square(p) + 17)))
\t - square(y - s)/

Related

Parsing an excel sheet with VBA

Scenario: In my worksheet I have data in multiple columns on the following format (this is an ASCII generated table to facilitate visualization, the symbols are not on the original spreadsheet):
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| Count | Indentifier1 | Identifier2 | Identifier3 | ProductName | Location | Type | Status | RegistryDate |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 1 | azjzjzj3611a | | | Super electric board - high load | SEA | General | Sold out -- Used -- | 4/17/2019 4:19 |
| | | | | | | | Good | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 2 | y000zj9y30 | | | electric board - low battery | SEA | General | Sold out -- Used -- Good | 5/12/2015 3:48 |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 3 | | | | Super jet-ski 01 Special | SHORE | TEST - Utility - Vehicle | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 4 | a30y970y3 | | | Super jet-ski 01 Special | SHORE | TEST - Utility - Vehicle | Used - Good | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 5 | | | | Ball 10-Type1 | BEACH | TEST - Utility - Small-Item | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 6 | azjzjzja9zjy9 | | | Ball 10-Type1 | BEACH | | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 7 | azjzjzja9zjy9 | | | Ball 10-Type1 | BEACH | TEST - Utility - Small-Item | Sold out -- Used - Good | 6/10/2013 0:00 |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 8 | a3044aa69 | 1007750 | | Ball 10-Type1 | | | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 9 | | | | Ball 10-Type1 | BEACH | TEST - Utility - Small Unit | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 10 | a3044aa69 | | BLL101 | Ball 10-Type1 | BEACH | TEST - Utility - Small Unit | Used - Good | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 11 | a3044aa69 | 1007750 | BLL101 | BALL 10-TYPE1 | Beach | TEST - Utility | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 12 | y0003aa67 | 36021 | | Ball 5-Type1 | | | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 13 | | | | Ball 5-Type1 | RIDGE | Group - Special | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 14 | y0003aa67 | | | Ball 5-Type1 | RIDGE | | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 15 | y0003aa67 | | BLL051 | Ball 5-Type1 | RIDGE | Group - Special | Used - Good | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
| 16 | y0003aa67 | 36021 | BLL051 | BALL 5-TYPE1 | Ridge | Group - Special | | |
+-------+---------------+-------------+-------------+----------------------------------+----------+-----------------------------+--------------------------+----------------+
Obs.: As per the table, the data can have multiple entries, where different information is displayed in each column. The differences may be either the format (upper/lower-case) or content (has data or not).
Objective: I am trying to retrieve the information from this table, without loosing data. Ex: If two rows have the same data, but one is lower case whereas the other is upper case, either could be retrieved (no preference), but if there is different data (maybe there is a slight difference in the item name or status), I am trying to retrieve all the data.
Done so far: I was able to simple create an array, loop it, and compare the data manually, but the result is sub-optimal, since it just aggregates the data in the same cell where it is different. Which would still require manual checking/cleaning.
Obs2.: This table has around 22 thousand rows.
Obs3.: Another issue of this data-set is that none of the columns is completely filled. Sometimes I have data for all identifiers and item name, sometimes an identifier is missing, sometimes the name is missing, and sometimes just one identifier is available (no name or anything else).
Question: Is there a way to do this?
Wanted output:
+-------+--------------+-------------+-------------+------------------------------+----------+-----------------------------+--------------------------+----------------+
| Count | Indentifier1 | Identifier2 | Identifier3 | ProductName | Location | Type | Status | RegistryDate |
+-------+--------------+-------------+-------------+------------------------------+----------+-----------------------------+--------------------------+----------------+
| 1 | azjzjzj3611a | | | Super electric | SEA | General | Sold out -- Used -- | 4/17/2019 4:19 |
| | | | | board - high load | | | Good | |
+-------+--------------+-------------+-------------+------------------------------+----------+-----------------------------+--------------------------+----------------+
| 2 | y000zj9y30 | | | electric board - low battery | SEA | General | Sold out -- Used -- Good | 5/12/2015 3:48 |
+-------+--------------+-------------+-------------+------------------------------+----------+-----------------------------+--------------------------+----------------+
| 3 | a30y970y3 | | | Super jet-ski 01 Special | SHORE | TEST - Utility - Vehicle | Used - Good | |
+-------+--------------+-------------+-------------+------------------------------+----------+-----------------------------+--------------------------+----------------+
| 4 | a3044aa69 | 1007750 | | Ball 10-Type2 | BEACH | TEST - Utility - Small-Item | Sold out -- Used - Good | 6/10/2013 0:00 |
+-------+--------------+-------------+-------------+------------------------------+----------+-----------------------------+--------------------------+----------------+
| 5 | a3044aa69 | 1007750 | BLL101 | Ball 10-Type1 | BEACH | TEST - Utility - Small Unit | Used - Good | |
+-------+--------------+-------------+-------------+------------------------------+----------+-----------------------------+--------------------------+----------------+
| 6 | y0003aa67 | 36021 | BLL051 | BALL 5-TYPE1 | Ridge | Group - Special | Used - Good | |
+-------+--------------+-------------+-------------+------------------------------+----------+-----------------------------+--------------------------+----------------+
Code for array approach:
Sub cleanup_detail()
Dim raw_array As Variant
Dim w As Workbook
Dim loopvar1 As Long
Set w = ThisWorkbook
raw_array = w.Worksheets("Sheet1").UsedRange
For loopvar1 = 2 To UBound(raw_array, 1)
If raw_array(loopvar1 + 1, 2) = "" Or raw_array(loopvar1 + 1, 2) = "0" Then
If raw_array(loopvar1 + 1, 3) = "" Or raw_array(loopvar1 + 1, 3) = "0" Then
If raw_array(loopvar1 + 1, 4) = "" Or raw_array(loopvar1 + 1, 4) = "0" Then
If raw_array(loopvar1 + 1, 5) = "" Or raw_array(loopvar1 + 1, 5) = "0" Then
Next loopvar1
ElseIf raw_array(loopvar1 + 1, 5) = raw_array(loopvar1, 5) Then
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 2) = raw_array(loopvar1 + 1, 2) & "/" & raw_array(loopvar1, 2)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 3) & "/" & raw_array(loopvar1, 3)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 4) & "/" & raw_array(loopvar1, 4)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 5)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 6) & "/" & raw_array(loopvar1, 6)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 7) & "/" & raw_array(loopvar1, 7)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 8) & "/" & raw_array(loopvar1, 8)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 9) & "/" & raw_array(loopvar1, 9)
End If
ElseIf raw_array(loopvar1 + 1, 4) = raw_array(loopvar1, 4) Then
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 2) = raw_array(loopvar1 + 1, 2) & "/" & raw_array(loopvar1, 2)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 3) & "/" & raw_array(loopvar1, 3)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 4)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 5) & "/" & raw_array(loopvar1, 5)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 6) & "/" & raw_array(loopvar1, 6)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 7) & "/" & raw_array(loopvar1, 7)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 8) & "/" & raw_array(loopvar1, 8)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 9) & "/" & raw_array(loopvar1, 9)
End If
ElseIf raw_array(loopvar1 + 1, 3) = raw_array(loopvar1, 3) Then
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 2) = raw_array(loopvar1 + 1, 2) & "/" & raw_array(loopvar1, 2)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 3) & "/" & raw_array(loopvar1, 3)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 4) & "/" & raw_array(loopvar1, 4)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 5) & "/" & raw_array(loopvar1, 5)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 6) & "/" & raw_array(loopvar1, 6)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 7) & "/" & raw_array(loopvar1, 7)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 8) & "/" & raw_array(loopvar1, 8)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 9) & "/" & raw_array(loopvar1, 9)
End If
ElseIf raw_array(loopvar1 + 1, 2) = raw_array(loopvar1, 2) Then
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 2) = raw_array(loopvar1 + 1, 2)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 3) & "/" & raw_array(loopvar1, 3)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 4) & "/" & raw_array(loopvar1, 4)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 5) & "/" & raw_array(loopvar1, 5)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 6) & "/" & raw_array(loopvar1, 6)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 7) & "/" & raw_array(loopvar1, 7)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 8) & "/" & raw_array(loopvar1, 8)
w.Worksheets("Sheet1").Cells(loopvar1 + 1, 3) = raw_array(loopvar1 + 1, 9) & "/" & raw_array(loopvar1, 9)
End If
Next loopvar1
End Sub

Detecting XOR in Karnaugh Maps

I got the following Karnaugh Maps but I am still having problems working out the expression for XOR from each table.
Table 1
-------
WZ
00 01 11 10
-----------------------
00 | | | | 1 |
-----------------------
01 | 1 | | | |
-----------------------
XY 11 | | | | 1 |
-----------------------
10 | 1 | | | |
-----------------------
Table 2
-------
WZ
00 01 11 10
-----------------------
00 | | 1 | | |
-----------------------
01 | | | 1 | |
-----------------------
XY 11 | | 1 | | |
-----------------------
10 | | | 1 | |
-----------------------
It is XORs, but how can I easily deduce the XOR expressions?
I would not dismiss the variable z from the expression, because I think, the expression ¬z·(¬x·y·¬w + ¬x·w·¬y + ¬y·¬w·x + w·y·x) is not equal to (¬x·y·¬w + ¬x·w·¬y + ¬y·¬w·x + w·y·x). That would mean, that the K-map contains four doubles of ones, but there is only four singles.
I would rather find the expression in the K-map and then use the laws of Boolean algebra.
For the first table:
¬x·¬y·w·¬z + ¬x·y·¬w·¬z + x·y·w·¬z + x·¬y·¬w·¬z
¬z·((¬x + ¬y + w)·(¬x + y + ¬w)·(x + y + w)·(x + ¬y + ¬w)) //distributivity
¬z· (¬x + ¬y + w)·(¬x + y + ¬w)·(x + y + w)·(x + ¬y + ¬w) //relaxed syntax
¬z· (¬x·¬x + ¬x·y + ¬x·¬w + ¬y·¬x + ¬y·y + ¬y·¬w + w·¬x + w·y + w·¬w)·
(x·x + x·¬y + x·¬w + y·x + y·¬y + y·¬w + w·x + w·¬y + w·¬w) //distributivity
Because of the laws of
idempotence (e.g.: ¬x·¬x=¬x),
absorption (e.g.:¬x + ¬x·y=¬x)
and complementation (e.g.: ¬x·x=0)
the expression is equivalent to:
¬z· (¬x + 0 + ¬y·¬w + w·y + 0)·
( x + + 0 + y·¬w + + w·¬y + 0 )
¬z· (¬x + ¬y·¬w + w·y)·(x + y·¬w + w·¬y) //just formatted
¬z· (¬x·x + ¬x·y·¬w + ¬x·w·¬y
+ ¬y·¬w·x + ¬y·¬w·y·¬w + ¬y·¬w·w·¬y
+ w·y·x + w·y·y·¬w + w·y·w·¬y) //distributivity
¬z· ( 0 + ¬x·y·¬w + ¬x·w·¬y
+ ¬y·¬w·x + 0 + 0
+ w·y·x + 0 + 0 ) //using the three laws↑ again
¬z· (¬x·y·¬w + ¬x·w·¬y + ¬y·¬w·x + w·y·x) //how the 3-input XOR is defined
¬z· (x xor y xor w)
For the second table:
¬x·¬y·¬w·z + ¬x·y·w·z + x·y·¬w·z + x·¬y·w·z
z·((¬x + ¬y + ¬w)·(¬x + y + w)·(x + y + ¬w)·(x + ¬y + w)) //distributivity
z· (¬x + ¬y + ¬w)·(¬x + y + w)·(x + y + ¬w)·(x + ¬y + w) //relaxed syntax
z· (¬x·¬x + ¬x·y + ¬x·w + ¬y·¬x + ¬y·y + ¬y·w + ¬w·¬x + ¬w·y + ¬w·w)·
(x·x + x·¬y + x·w + y·x + y·¬y + y·w + ¬w·x + ¬w·¬y + ¬w·w) //distributivity
z· ( ¬x + + 0 + ¬y·w + + ¬w·y + 0 )·
( x + + 0 + y·w + + ¬w·¬y + 0 )
z· (¬x + ¬y·w + ¬w·y)·(x + y·w + ¬w·¬y) //just formatted
z· (¬x·x + ¬x·y·w + ¬x·¬w·¬y
+ ¬y·w·x + ¬y·w·y·w + ¬y·w·¬w·¬y
+ ¬w·y·x + ¬w·y·y·w + ¬w·y·¬w·¬y) //distributivity
z· ( 0 + ¬x·y·w + ¬x·¬w·¬y
+ ¬y·w·x + 0 + 0
+ ¬w·y·x + 0 + 0) //using the three laws↑ again
z· (¬x·y·w + ¬x·¬w·¬y + ¬y·w·x + ¬w·y·x) //how the 3-input XNOR is defined
z· (x xnor y xnor w)
The first table contains an Xor expression :
`First table`
w
\ wz ___________
xy \-----------------------+
| | | | 1 |
+-----+-----+-----+-----+
| 1 | | | | |
+-----+-----+-----+-----+ | y
| | | | | 1 | |
x | +-----+-----+-----+-----+
| | 1 | | | |
+-----------------------+
___________
z
as you could see the middle of the table (Z area) is fake.
that is, the table function is :
F(Table1) = w'x'yz' + wx'y'z' + w'xy'z' + wxyz'
in binary form you could see a zero column :
F(Table) = 0010 eliminating Z F(xor)= 001
0100 ---------------\ 010
1110 ---------------/ 111
1000 100
^--> fake
and the final table must be something like this :
`simplified xor table`
w
\ w 0 __1__
xy \-----------+
00 | | 1 |
+-----+-----+
01 | 1 | | |
+-----+-----+ | y And " F = wy' + w'y " is an Xor only
|10 | 1 | | | between 2 variables, right?
x | +-----+-----+
|11 | | 1 |
+-----------+
The second table just contains an Xnor expression of the first one :
`Second Table`
F(Table2) = w'xyz + wxy'z + w'x'y'z + wx'yz
w
\ wz ___________
xy \-----------------------+ negation of table 2 is table 1 and vise versa
| | 1 | | | F(Table2) = 1101 F(Table2)'= F(Table1) = 0010
+-----+-----+-----+-----+ 1011 0100
| | | 1 | | | 0001 1110
+-----+-----+-----+-----+ | y 0111 1000
| | | 1 | | | | ^--> fake ^
x | +-----+-----+-----+-----+
| | | | 1 | |
+-----------------------+
^ ___________ ^
^ z ^
^ ^
^--------z'-------^
the final table is:
w
\ w 0 __1__
xy \-----------+
00 | 1 | |
+-----+-----+
01 | | 1 | |
+-----+-----+ | y And " F = w'y' + wy " is an Xnor
|10 | | 1 | |
x | +-----+-----+
|11 | 1 | |
+-----------+
Always remember the tables that contain the zigzag pattern
are either an Xor or Xnor expression.
Just put a copy of this map on the right hand side of it (or left, no difference) and then choose two tilted cubes.
Now, we write the simplified function for both of them:
(A = 1) (AND) (B=0 when C=1 and B=1 when C=0)
(OR)
(A = 0) (AND) (B=0 when C=0 and B=1 when C=1)
that finaly gives this:
(A AND (B XOR C)) OR (¬A AND (B XNOR C))
Basic rule for xor is that it gives 1 when odd number of input are 1.
So in KMAP just see if 1 is present in all the odd number of 1's.
Like WXYZ ( 0010, 1110 etc) if all gives 1 than there is a XOR in kmap.

How to print vertically in C?

I have to printfs in a loop an I want to print the output in two lines, instead of intermingled on one line.
Like this:
printf("| %-7.2f ", Fahrenheit);
which produces:
| -508.00 | -463.00 | -418.00 | -373.00 | -328.00 | -283.00 |
When I add printf("| %-6d", Celsius); under the printf above, it prints right next to/in the middle of my first printf.
I want the output to be like:
| -508.00 | -463.00 | -418.00 | -373.00 | -328.00 | -283.00 |
| -300 | -275 | -250 | -225 | -200 | -175 | -150 | -125|
instead of the two sets of values being intermingled on the same line.
part of my code:
for(Celsius = CelsiusMin;Celsius <= CelsiusMax; Celsius += CelsiusStep)
{
Fahrenheit = FahrenheitZero + Celsius * CelsiusToFahrenheit;
printf("| %-7.2f ", Fahrenheit);
printf("| %-6d", Celsius);
}
return EXIT_SUCCESS;
}
You can't directly have one sequence of printf() statements writing to line 1 and a second concurrent sequence of printf() statements writing to line 2, so you're going to have to fake it.
You probably need something that builds up the two lines of output, and then prints them when they're ready:
char line1[128];
char line2[128];
char *next1 = line1;
char *next2 = line2;
for (int c = -325; c <= -125; c += 25)
{
double f = (c + 40.0) * (9.0 / 5.0) - 40.0;
next1 += sprintf(next1, "| %-7.2f ", f);
next2 += sprintf(next2, "| %-7d ", c);
}
printf("%s|\n", line1);
printf("%s|\n", line2);
Sample output:
| -553.00 | -508.00 | -463.00 | -418.00 | -373.00 | -328.00 | -283.00 | -238.00 | -193.00 |
| -325 | -300 | -275 | -250 | -225 | -200 | -175 | -150 | -125 |
The conversion formula is simpler than the usual one you see quoted, and is symmetric for converting °F to °C or vice versa, the difference being the conversion factor (9.0 / 5.0) vs (5.0 / 9.0). It relies on -40°C = -40°F. Try it:
C =  0°C; (C+40) = 40; (C+40)*9 = 360; (C+40)*9/5 = 72; (C+40)*9/5-40 = 32°F.
F = 32°F; (F+40) = 72; (F+40)*5 = 360; (F+40)*5/9 = 40; (F+40)*5/9-40 =  0°C.
You might do better with the degrees Celsius as printed as a double too; I kept the integer representation you chose, but made sure the numbers line up on the two lines.
FYI: Absolute zero is -273.15°C, 0K, -459.57°F. So you're attempting to print non-existent temperatures.

Trouble with operation

So I am making a Caesar cipher program I have the encryption working just fine it is the decryption I am having trouble with.
Here is the code that works for encryption on uppercase letters:
if (isupper(p[i])){
char c = ((p[i] - 'A') + k % 26) + 'A';
}
Now I would think that decryption would be:
if (isupper(pp[i])){
char c = (abs((p[i] - 'A') - k) % 26) + 'A';
}
The issue that I'm having is that if k=1 and p[i]='A' it will just output the letter 'B' and not 'Z' it does not wrap around like it should so if k=2 and p[i]='A' it should output the letter 'Y'. It works if k=1 and p[i]='B' it will output 'A' thanks for any help.
This should do it:
if (isupper(p[i])){
char c = (p[i] - 'A' + 26 - k) % 26) + 'A';
}
The + 26 gives you your wrapping
Think of it this way (the three digit number format is just to make things line up nicely):
| 000 | 001 | 002 | ... | 024 | 025 | plain
| A | B | C | ... | Y | Z |
| 003 | 004 | 005 | ... | 001 | 002 | crypto
Now, recognize that
(n + 26) % 26 === (n % 26)
So:
| 000 | 001 | 002 | ... | 024 | 025 | plain
| A | B | C | ... | Y | Z |
| 029 | 030 | 031 | ... | 053 | 054 | crypto
is equivalent to the above when you consider modulo 26
This makes life a lot easier. The plaintext symbol set is made up of a contiguous set of integers from 'A' to 'A' + 25. The problem is that the ciphertext symbol set is not contiguous... there's a discontinuity at 025. By adding 26, you can convert the cipher text to a contiguous range from 'A' + k + 26 to 'A' + k + 49.
It's much easier then to map your contiguous ciphertext symbol set to your plaintext symbol set.
Since the Caesar code could be a shift in either direction and the decrypt is just the opposite shift, you could combine this to
boolean decrypt;
int k;
...
k = k % 26; // Ensure that the shift doesn't include any wrapping
if(decrypt) {
k *= -1;
}
if (isupper(p[i])){
char c = (p[i] - 'A' + 26 + k) % 26) + 'A';
}
In the encryption,
((p[i] - 'A') + k % 26) + 'A'
consider that it is evaluated as
t1 = p[i] - 'A'
t2 = k % 26
result = t1 + t2 + 'A'
That probably is not what you intended. The decryption would not reverse that arithmetic, mostly because the extra grouping changes the order of operations.
You are not considering the fact that they wrap around, try it like this:
if ((p[i] - 'A' - k) < 0 )
c = 'Z' - (abs(p[i] - 'A' - k) % 26) + 1;
else
c = (abs(p[i] - 'A' - k) % 26) + 'A';
And I think you don't need the moudulo "%" either.

Multiplication algorithm for abritrary precision (bignum) integers

I'm writing a small bignum library for a homework project. I am to implement Karatsuba multiplication, but before that I would like to write a naive multiplication routine.
I'm following a guide written by Paul Zimmerman titled "Modern Computer Arithmetic" which is freely available online.
On page 4, there is a description of an algorithm titled BasecaseMultiply which performs gradeschool multiplication.
I understand step 2, 3, where B^j is a digit shift of 1, j times.
But I don't understand step 1 and 3, where we have A*b_j. How is this multiplication meant to be carried out if the bignum multiplication hasn't been defined yet?
Would the operation "*" in this algorithm just be the repeated addition method?
Here is the parts I have written thus far. I have unit tested them so they appear to be correct for the most part:
The structure I use for my bignum is as follows:
#define BIGNUM_DIGITS 2048
typedef uint32_t u_hw; // halfword
typedef uint64_t u_w; // word
typedef struct {
unsigned int sign; // 0 or 1
unsigned int n_digits;
u_hw digits[BIGNUM_DIGITS];
} bn;
Currently available routines:
bn *bn_add(bn *a, bn *b); // returns a+b as a newly allocated bn
void bn_lshift(bn *b, int d); // shifts d digits to the left, retains sign
int bn_cmp(bn *a, bn *b); // returns 1 if a>b, 0 if a=b, -1 if a<b
I wrote a multiplication algorithm a while ago, and I have this comment at the top. If you have two numbers x and y of the same size (same n_digits) then you would multiply like this to get n, which would have twice the digits. Part of the complexity of the algorithm comes from working out which bits not to multiply if n_digits is not the same for both inputs.
Starting from the right, n0 is x0*y0 and you save off the overflow. Now n1 is the sum of x1*y0 and y1*x0 and the previous overflow shifted by your digit size. If you are using 32 bit digits in 64 bit math, that means n0 = low32(x0*y0) and you carry high32(x0*y0) as the overflow. You can see that if you actually used 32 bit digits you could not add the center columns up without exceeding 64 bits, so you probably use 30 or 31 bit digits.
If you have 30 bits per digit, that means you can multiple two 8 digit numbers together. First write this algorithm to accept two small buffers with n_digits up to 8 and use native math for the arithmetic. Then implement it again, taking arbitrary sized n_digits and using the first version, along with your shift and add method, to multiply 8x8 chunks of digits at a time.
/*
X*Y = N
x0 y3
\ /
\ /
X
x1 /|\ y2
\ / | \ /
\ / | \ /
X | X
x2 /|\ | /|\ y1
\ / | \ | / | \ /
\ / | \|/ | \ /
X | X | X
x3 /|\ | /|\ | /|\ y0
\ / | \ | / | \ | / | \ /
\ / | \|/ | \|/ | \ /
V | X | X | V
|\ | /|\ | /|\ | /|
| \ | / | \ | / | \ | / |
| \|/ | \|/ | \|/ |
| V | X | V |
| |\ | /|\ | /| |
| | \ | / | \ | / | |
| | \|/ | \|/ | |
| | V | V | |
| | |\ | /| | |
| | | \ | / | | |
| | | \|/ | | |
| | | V | | |
| | | | | | |
n7 n6 n5 n4 n3 n2 n1 n0
*/
To do A*b_j, you need to do the grade school multiplication of a bignum with a single digit. You end up having to add a bunch of two-digit products together:
bn *R = ZERO;
for(int i = 0; i < n; i++) {
bn S = {0, 2};
S.digits[0] = a[i] * b_j;
S.digits[1] = (((u_w)a[i]) * b_j) >> 32; // order depends on endianness
bn_lshift(S, i);
R = bn_add(R, S);
}
Of course, this is very inefficient.

Resources