Wednesday, September 30, 2015

Amazon Store Card First Month Requires Manual Payment

I was charged late fee for not paying my first month statement. I checked online to make sure that I had recurring payments setup which it was. I then checked my email and found each one were sent prior to the end of the pay period.

Note that there will be two emails on the recurring payments. The first will be that you configured it, then it takes a couple weeks (13 days for me) for the company to configure the recurring payments. When that is complete a second email is sent.

Within the second email (yes, the grammar error was also in the email): 
Your request to change your Recurring Payment has been processed for your Amazon.com Store Card account ending in ****. You have selected to pay the the "statement balance" option for your monthly Recurring Payment . Payments will be made from your XXXXXXX account ending in **** on your payment due date.
The last statement would make you think that your first month would be paid on your due date. When I called into support, they said that the first month has to be paid manually. He did waive the late fee and said that the second month would be paid via the recurring payment process. Also to note, I did not have to wait long (maybe 3 minutes) on hold and the service rep was articulate, respectable, and quick.

Side note: If you are ever late on a credit card payment, you can typically call in to have the late fee waived if you typically pay it on time. My mom hated using the internet to pay so would only use the paper statement which for some reason she did not always receive. I have not not had any issues (at least with Visa or American Express) with support to have the fee waived.

Edit (10/13/2015) - You could wait till the next month, but if you don't, sync bank will call every, single day because you have an overdue balance. For how badly they seem to want your money, you think they have a manual trigger to use your automated payment information... but of course, that is not the case, and you have to enter all your bank info again.

This was the second time that I had called to sync bank support. This time to ask why I keep getting the calls because the automated message does not state why you should call the number or visit the website. Surprisingly, the support techs have been knowledgeable in the issues and were able to answer my questions directly and clearly without putting me on hold to ask a manager.

Edit (10/31/2015) - I started calls again but no messages, until very recently. This is when I found that my account had an overdue balance which is very odd because I didn't purchase anything. This is odd because I thought I paid after the last time I called and second I had automatic payment set up.

Well, automatic payment setup was my own error. For some reason my account number was off by a digit... which is odd because I usually copy/paste from the bank site. As for my payment, I could not find any records of my attempt to pay but I am almost positive that I did because I had complained last time that my automatic payment info didn't carry over. I remember having to enter all the information again. So, I'm not sure what really happened. Either way, I found an option to pay manually from the automatic payment so this time I didn't have to reenter any information.

And I really cannot repeat this enough, syncbank's support is just awesome again! Although I am not sure if the support person understood about my attempt to pay a month ago, she still was able to waive the late fee again. This time I made sure to check for emails and confirmations after I posted the payment. Prior to the call, I was seriously going to cancel the card.

8667711104 (866) 771-1104

Saturday, September 26, 2015

hackerrank Mr K marsh

This puzzle was quite the mind bender for me. I didn't know that performance was one of the requirements so my first attempt worked for the most part but failed some of the test cases due to timeouts. This was only my second challenge outside of the warmups.

The Timed Out Method


Briefly, my first attempt was simply iterate through each 'cell' and within each cell I iterated through all the possible perimeters. As it iterated, I just kept the largest, allowable perimeter. This of course had many, many loops. 1 loop to check so that is O(n^2), then another loop within the loop so another O(n^2) which would make it O(n^4). Then a final loop to validate the perimeter... which for simplicity say another n-order so at most O(n^5). Of course, I tried to cut corners by looking for largest perimeter and skip some loops, but that will be at best be O(n^5 / x) where x is some fixed value which will not outperform the size of the data.

Comparing my solution to a couple that I found on-line, I iterate through rows instead of columns. This is quite minor as long as you remain consistent which dimension goes to which, then they are essentially the same except for the terminology used in the notations or variables. A bigger difference is that I iterate from the largest potential perimeter. I don't think this made a huge difference depending on how the data is provided. Worst case O is the same either way.

Accepted Method


I attempted to write how I reached the need for each step in the code but this turned out to be very messy and tedious and likely very boring to read. But I hope this explanation would be more helpful than just reading the code.

Another matrix is used to calculate the number of marshes. This is used to determine if the top border or bottom border contains a marsh. This matrix contains the accumulation of marshes per row. Thus 'x.x.x.x.....x' will become '112233444445'. The reason for this is to easily identify that 11 is a set, 22 is a set, and so on and so forth. When comparing the left part of the perimeter to the right, if the numbers are different that means that a marsh exists. But when the iteration reaches (for example) as 4 for the top left corner while the top right corner is on the last 4, then a border is found without having to iterate through each cell to find a marsh.

The first logical loop is to identify the left and right side of the perimeter. I chose to start with the far left and the far right (the other solutions start with the far left and the second column which is fine too). This requires two loops to identify all possible widths with different starting points.

The next loop is to identify the height of the perimeter. I started with the top most and bottom most. But as I debugged, I found that the subset perimeters are always true. Thus if I started with the smallest height, I eliminate one of the loops.

Depending on the loop, this determines whether the perimeter should be calculated or not. Initially, we assume we have no rows. When we finally iterate to a partial row with no marshes, we set the initial row.

Iterate to the next row, if the row has no marshes, then calculate the perimeter (store only if it is larger than a previous calculation). If the row contains an x, then do not calculate the perimeter but continue to iterate because it is still a potential side. If the end points of the row contains an x, then that is the end of the iteration for that top boundary by resetting the initial row. Continue to iterate to find other potential loops. Logically, the checks should be in reverse order (ie marshes as endpoints, marshes in boundary, then no marshes).

Hopefully that would be of some help while going over the other codes online.

Attempt to Illustrate the Algorithm

First find top part of the fence. If the land is:
x.x.x.x.....x
x.x...x.....x
x.x...x..x..x
x.x...x.....x
x.x...x..x..x

You'll find one acceptable top in line one, column 8-12. Then look if the next row is a potential bottom. If a potential bottom, record the row. If not acceptable, then do not record as potential row. If To be efficient, check if the left-most and right-most are marsh-free. If marsh-free, check if the two values are the same. This will reduce a loop to check all spaces are marsh-free.

x.x.x.x.....x
x.x...x.....x (potential row)
x.x...x..x..x (not potential row)
x.x...x.....x (potential row)
x.x...x..x..x (not potential row)

After looping throw all rows, you'll find that row #4 will create the largest perimeter for this iteration. If the perimeter is larger than the last perimeter (always true for the first set), record new perimeter value.

x.x.x.x.....x
x.x...x.....x
x.x...x..x..x
x.x...x.....x
x.x...x..x..x

Repeat above steps for all other valid top rows. I did not include any logic to exclude subsets but one could be included to make the algorithm faster (efficiency is debatable as it probably requires another matrix).

There is one other major set but you'll find is smaller so will not be recorded.

x.x.x.x.....x
x.x...x.....x
x.x...x..x..x
x.x...x.....x
x.x...x..x..x

Edit (10/31/2015):
Added an illustration portion to hopefully better show what is going on.

Reference

https://www.hackerrank.com/challenges/mr-k-marsh

Saturday, September 19, 2015

C# Exception when using foreach, datatable, and modifying collection

InvalidOperationException was unhandled by user code
An exception of type 'System.InvalidOperationException' occurred in System.Data.dll but was not handled in user code.
Additional information: Collection was modified; enumeration operation might not execute.

I was curious how the foreach worked when I modified the collection. I came about this because I had a list of available options but wanted to remove the ones that already existed in another dataset.

Basically the code went like:
foreach(DataRow dr1 in dt1.Rows)
                {
                    foreach(DataRow dr2 in dt2.Rows)
                    {
                        if (dr1["Id"].ToString() == dr2["Id"].ToString())
                            dt1.Rows.Remove(dr1);
                    }
                }

This causes the above error because I am doing what the error message says. Basically, I had to switch to a for loop instead. If you loop backwards, you can avoid a lot of other checks.

Saturday, September 12, 2015

Storing Approximate or Partial Dates in Database

One of the common issues that I have in programming is how to store questionable dates. There are all different forms of questionable dates, but I have primarily been focused on partial dates where I may or may not have the date. The most common property is the a person's birthday. After a few different ways of storing the date, I have found that having an additional column to store the certainty of the date works best for me thus far.

In MS SQL, I have an additional binary column. I will have two columns, DOB (date) and DOBAppr (binary(1)). DOBAppr contains the certainty of DOB. If DOBAppr is 0 then the date is known exactly. If 1, the day is uncertain. In the application, I will only display Month and Year if DOBAppr is 1. If 2, the month is uncertain. This is uncommon to have only the year and day but the possibility is there. One example is when someone does not explicitly share their DOB but has mentioned that they shared the same day (and you know how old they are). If 3, the day and month is unknown. So basically, I have set it up like a binary flag. 4 is unknown year, 5 is unknown year and date, 6 is unknown year and month, 7 is all unknown.

In the previous solution, I used to broken the date into multiple fields, day (tinyint), month (tinyint), and year (smallint). If the value was unknown, I would leave the field as null or use 0 if null is not allowed. Although slightly easier to build the tables, there was quite a bit of overhead to programming. There are other insignificant inefficiencies. This solution has always just bugged me because it was just not a perfect fit even though it worked sufficiently.

Recently, I have expanded on my application and found other uses to using a flags. I was trying to store data on music genres and one of the field is origins. Often in sources, I only get date ranges or decades. So by simply expanding my flags to include the 4th-bit for decades, 5th-bit for centuries, and 6th-bit for millenniums.

While on this expansion, there is also another flag that I could use in the future like approximation (ie circa, c, ca, circ, or cca). Quite similar to partial dates, but this would also mean that the value provided may be incorrect. For example for circa 2015, this could include 2014 or 2016 (or a wider range depending on the object). For partial dates, 2015 would have high confidence that it is correct (or at least a very small chance for error). Although I have no implemented this yet, the solution still gives this flexibility. I probably would use the last bit.

Sunday, September 6, 2015

TED: Alternate Solution to Addiction

http://www.ted.com/talks/johann_hari_everything_you_think_you_know_about_addiction_is_wrong

Interesting talk that has changed my views on addiction (chemical hooks) vs reconnecting addicts to other values.