Calculate days between two dates in Haskell from a custom date ADT - date

-- a)
leapYear :: Int -> Bool
leapYear n = (n `mod` 4 == 0) && ( (n `mod` 100 /= 0) || (n `mod` 400 == 0) )
-- b)
data Month = Jan | Feb | Mar | Apr | May | Aug | Jun | Jul | Sep | Oct | Nov | Dec
deriving (Enum, Eq, Show)
-- c)
type Day = Int
type Year = Int
data Date = Date Day Month Year
deriving Show
-- d)
dateIsValid :: Date -> Bool
dateIsValid (Date d m y) | y < 0 || y > 9999 = False
| d < 0 = False
| m `elem` [Jan, Mar, May, Jul, Aug, Oct, Dec] = d < 32
| m `elem` [Apr, Jun, Sep, Nov, Feb] = d < 31
| m == Feb = if leapYear y then d < 30 else d < 29
| otherwise = False
-- e)
daysBetween :: Date -> Date -> Int
daysBetween (Date a b c) (Date x y z) = if dateDay (Date a b c) > dateDay (Date x y z)
then dateDay (Date a b c) - dateDay (Date x y z)
else dateDay (Date x y z) - dateDay (Date a b c)
where monthDay m = case m of Jan -> 0
Feb -> 31
Mar -> 59
Apr -> 90
May -> 120
Jun -> 151
Jul -> 181
Aug -> 211
Sep -> 243
Oct -> 273
Nov -> 304
Dec -> 334
countLeapYears (Date d m y) | m `elem` [Jan, Feb, May] = (y-1) `div` 4 - (y-1) `div` 100 + (y-1) `div` 400
| otherwise = y `div` 4 - y `div` 100 + y `div` 400
dateDay (Date d m y) = d + monthDay m + (y-1)*365 + countLeapYears (Date d m y)
getMonthNr :: Month -> Int
getMonthNr m = case m of Jan -> 1
Feb -> 2
Mar -> 3
Apr -> 4
May -> 5
Jun -> 6
Jul -> 7
Aug -> 8
Sep -> 9
Oct -> 10
Nov -> 11
Dec -> 12
-- f)
data Dow = Mon | Tue | Wen | Thu | Fri | Sat | Sun
deriving Show
-- g)
weekday :: Date -> Dow
weekday (Date d m y) = case daysBetween (Date d m y) (Date 3 Jan 2000) `mod` 7 of 0 -> Sun
1 -> Mon
2 -> Tue
3 -> Wen
4 -> Thu
5 -> Fri
_ -> Sat
I have got this code where I need to calculate the number of days between two days and then find the weekday of that date. While this code is correct in finding the answer for the given examples in the exercises daysBetween (Date 4 Nov 2021) (Date 1 Jan 2000) → 7978 and January 1st, 2021 was a Friday, it shows problems with most other dates. One of my tests involved the date Date 13 Aug 2009 and Date 3 Jan 2000 where the error is one day. I am not allowed to use predefined functions to find the difference between two dates or the specific weekday. Is there something wrong with the logic I have used? Or is there another way to implement an algorithm that searches for the difference between two days?
getMonthNr can be ignored or not, since I wrote it down while experimenting and left it there in case I would need it.
Edit: After correcting the code a 1 day shift occurs when the days are a few years apart (almost a decade) or a 2 day shift when the days are centuries to a few millennia apart.

Do you just have Aug in the wrong place? It should be between Jul and Sep but it is between May and Jun in your code.

Related

Problems with fprintf format (Matlab)

I want to correct variables' format in a txt file (show at the end, replace spaces for tab spaces), using the next Matlab code (previous import):
id = fopen('datoscorfecha.txt', 'w');
fprintf(id, '%5s %3s %3s %3s %4s %3s %6s\n',...
'fecha', 'dia','mes', 'ano', 'hora', 'min', 'abs370');
datos = cat(2,dia, mes, ano, hora, min1, abs370);
datos = datos';
fecha = Fecha'; % Imported as a string
fprintf(id, '%16s %2i %2i %4i %2i %2i %8.4f\n',...
fecha, datos);
fclose(id);
type datoscorfecha.txt
But I get this error:
Error using fprintf
Unable to convert 'string' value to
'int64'.
Fecha dia mes ano hora min abs370
03/06/2016 00:00 3 6 2016 0 0 29.356218
03/06/2016 00:05 3 6 2016 0 5 30.45703
03/06/2016 00:10 3 6 2016 0 10 27.53877
03/06/2016 00:15 3 6 2016 0 15 23.19832
03/06/2016 00:20 3 6 2016 0 20 22.333924
03/06/2016 00:25 3 6 2016 0 25 22.086426
03/06/2016 00:30 3 6 2016 0 30 20.933898
Maybe something like this can allow you to replace the spaces with tabs. Here I read the text file using the textscan() function and separate the columns. I also parse each value/term as a string. By using the writematrix() function I can write the data to a new text file the but with the Delimeter set to tab.
Text.txt (Input)
Fecha dia mes ano hora min abs370
03/06/2016 00:00 3 6 2016 0 0 29.356218
03/06/2016 00:05 3 6 2016 0 5 30.45703
03/06/2016 00:10 3 6 2016 0 10 27.53877
03/06/2016 00:15 3 6 2016 0 15 23.19832
03/06/2016 00:20 3 6 2016 0 20 22.333924
03/06/2016 00:25 3 6 2016 0 25 22.086426
03/06/2016 00:30 3 6 2016 0 30 20.933898
datoscorfecha.txt (Output)
Fecha dia mes ano hora min abs370
03/06/2016 00:00 3 6 2016 0 0 29.3562
03/06/2016 00:05 3 6 2016 0 5 30.4570
03/06/2016 00:10 3 6 2016 0 10 27.5388
03/06/2016 00:15 3 6 2016 0 15 23.1983
03/06/2016 00:20 3 6 2016 0 20 22.3339
03/06/2016 00:25 3 6 2016 0 25 22.0864
03/06/2016 00:30 3 6 2016 0 30 20.9339
Full Script:
File_ID = fopen("Text.txt");
Data = textscan(File_ID, '%s %s %s %s %s %s %s %s', 'Delimiter',' ');
fclose(File_ID);
% Data = readtable("Text.txt");
Column_1 = string(Data{:,1});
Column_2 = string(Data{:,2});
Column_3 = string(Data{:,3});
Column_4 = string(Data{:,4});
Column_5 = string(Data{:,5});
Column_6 = string(Data{:,6});
Column_7 = string(Data{:,7});
Column_8 = string(Data{:,8});
for Index = 2: length(Column_8)
Number = str2double(char(Column_8(Index,1)));
Number = num2str(Number);
Decimal_String = split(Number,".");
Decimal_String = Decimal_String{2};
if length(Decimal_String) ~= 4
Number = string(Number) + "0";
end
Column_8(Index,1) = Number;
end
Table = [Column_1 Column_2 Column_3 Column_4 Column_5 Column_6 Column_7 Column_8];
writematrix(Table,"datoscorfecha.txt",'Delimiter','tab');
type datoscorfecha.txt
Ran using MATLAB R2019b

How to convert Julian dates to and from different representations using integer arithmetic

The question is how to convert dates between different representations using integer arithmetic, specifically between a "Days since year zero ( Jan 1, 0000 )" representation, and either Year/Day or Year/Month/Day forms, in the Julian calendar. The different representations are useful for date input, date display and date arithmetic.
Specifically, a date such as June 5th, 2020 is represented in Year/Month/Day representation as
2020 * 512 + 6 * 32 + 5
or in Year/Day representation as
2020 * 512 + 157 ( June 5th is day 157 in a leap year ).
Yesterday, I wanted to write code to do this, and surprisingly didn't find much help online, so I thought I would document my solution here ( I will be answering my own question ).
First here is code for converting from Year/Day to Days ( the language is very similar to Microsoft SQL Server T-SQL, except variable names do not begin with '#', and there is a 'bool" data type ) :
CREATE FUNCTION [date].[YearDayToDays]( yd int ) RETURNS int AS
BEGIN
-- Given a date in Year/Day representation stored as y * 512 + d where 1 <= d <= 366 ( so d is day in year )
-- returns the number of days since "day zero" (1 Jan 0000)
-- using the Gregorian calendar where days divisible by 4 are leap years, except if divisible by 100, except if divisible by 400.
DECLARE y int, d int, cycle int
-- Extract y and d from yd.
SET y = yd / 512, d = yd % 512 - 1
SET cycle = y / 400, y = y % 400 -- The Gregorian calendar repeats every 400 years.
-- Result days come from cycles, from years having at least 365 days, from leap years and finally d.
-- 146097 is the number of the days in a 400 year cycle ( 400 * 365 + 97 leap years ).
RETURN cycle * 146097
+ y * 365
+ ( y + 3 ) / 4 - ( y + 99 ) / 100 + ( y + 399 ) / 400
+ d
END
Now the opposite conversion, Days to Year/Day:
CREATE FUNCTION [date].[DaysToYearDay]( days int ) returns int as
begin
-- Given a date represented by the number of days since 1 Jan 0000
-- calculate a date in Year/Day representation stored as
-- y * 512 + d where d is 1..366
DECLARE y int, d int, cycle int
-- 146097 is the number of the days in a 400 year cycle ( 400 * 365 + 97 leap years )
SET cycle = days / 146097
SET days = days % 146097
SET y = days / 365
SET d = days % 365
-- Need to adjust d to allow for leap years.
-- Leap years are 0, 4, 8, 12 ... 96, not 100, 104 ... not 200... not 300, 400, 404 ... not 500.
-- Adjustment as function of y is 0 => 0, 1 => 1, 2 =>1, 3 => 1, 4 => 1, 5 => 2 ..
SET d = d - ( y + 3 ) / 4 - ( y + 99 ) / 100 + ( y + 399 ) / 400
IF d < 0
BEGIN
SET y = y - 1
SET d = d + CASE WHEN date.IsLeapYear( y ) THEN 366 ELSE 365 END
END
RETURN date.YearDay( cycle * 400 + y, d + 1 )
END
The auxiliary function date.IsLeapYear:
CREATE FUNCTION [date].[IsLeapYear]( y int ) RETURNS bool AS
BEGIN
RETURN y % 4 = 0 AND ( y % 100 != 0 OR y % 400 = 0 )
END
and date.YearDay :
CREATE FUNCTION [date].[YearMonthDay]( year int, month int, day int ) RETURNS int AS
BEGIN
RETURN year * 512 + month * 32 + day
END
Conversion from Year/Day to Year/Month/Day:
CREATE FUNCTION [date].[YearDayToYearMonthDay]( yd int ) returns int AS
BEGIN
DECLARE y int, d int, leap bool, fdm int, m int, dim int
SET y = yd / 512
SET d = yd % 512 - 1
SET leap = date.IsLeapYear( y )
-- Jan = 0..30, Feb = 0..27 or 0..28
IF NOT leap AND d >= 59 SET d = d + 1
SET fdm = CASE
WHEN d < 31 THEN 0 -- Jan
WHEN d < 60 THEN 31 -- Feb
WHEN d < 91 THEN 60 -- Mar
WHEN d < 121 THEN 91 -- Apr
WHEN d < 152 THEN 121 -- May
WHEN d < 182 THEN 152 -- Jun
WHEN d < 213 THEN 182 -- Jul
WHEN d < 244 THEN 213 -- Aug
WHEN d < 274 THEN 244 -- Sep
WHEN d < 305 THEN 274 -- Oct
WHEN d < 335 THEN 305 -- Nov
ELSE 335 -- Dec
END
SET dim = d - fdm
SET m = ( d - dim + 28 ) / 31
RETURN date.YearMonthDay( y, m+1, dim+1 )
END
The auxiliary function date.YearMonthDay:
CREATE FUNCTION [date].[YearMonthDay]( year int, month int, day int ) RETURNS int AS
BEGIN
RETURN year * 512 + month * 32 + day
END
Finally conversion from Year/Month/Day to Year/Day:
CREATE FUNCTION [date].[YearMonthDayToYearDay]( ymd int ) RETURNS int AS
BEGIN
DECLARE y int, m int, d int
-- Extract y, m, d from ymd
SET d = ymd % 32, m = ymd / 32
SET y = m / 16, m = m % 16
-- Incorporate m into d ( assuming Feb has 29 days ).
SET d = d + CASE
WHEN m = 1 THEN 0 -- Jan
WHEN m = 2 THEN 31 -- Feb
WHEN m = 3 THEN 60 -- Mar
WHEN m = 4 THEN 91 -- Apr
WHEN m = 5 THEN 121 -- May
WHEN m = 6 THEN 152 -- Jun
WHEN m = 7 THEN 182 -- Jul
WHEN m = 8 THEN 213 -- Aug
WHEN m = 9 THEN 244 -- Sep
WHEN m = 10 THEN 274 -- Oct
WHEN m = 11 THEN 305 -- Nov
ELSE 335 -- Dec
END
-- Allow for Feb being only 28 days in a non-leap-year.
IF m >= 3 AND NOT date.IsLeapYear( y ) SET d = d - 1
RETURN date.YearDay( y, d )
END
I hope it's useful to someone, and I hope it's correct - I have tested by generating test ranges of days to check the generated calendar looks correct, with the correct number of days in each month, especially February. The functions do not check whether the input is valid, that is assumed. This is part of a project to implement SQL in C#.

How to calculate the day of the week based on unix time

I know that there are functions/classes in most programming languages to do that, but I would like to know the calculation.
So: How do I get from the unix time in seconds to a day-number (e.g. 0 for Sunday, 1 for Monday etc.)?
Thanks in advance. BTW: this is my first post on Stack Overflow.
The problem you ask is reasonably easy, compared to how ridiculously complicated other date/time functions can be (e.g. Zeller's congruence).
Unix time is defined as the number of seconds elapsed after January 1, 1970, at 00:00 (midnight) UTC.
You can look up a calendar to find that 1970-01-01 was a Thursday. There are 24 * 60 * 60 = 86400 seconds in a day.
Therefore values 0 to 86399 are Thursday, 86400 to 172799 are Friday, 172800 to 259199 are Saturday, etc. These are blocks of 86400 seconds aligned at 0.
Suppose T is your Unix timestamp. Then floor(T / 86400) tells you the number of days after 1970-01-01. 0 = Thursday January 1st; 1 = Friday January 2nd; 2 = Saturday January 3rd; etc.
Add 4 and modulo 7. Now 0 → 4; 1 → 5; 2 → 6; 3 → 0; 4 → 1; 5 → 2; 6 → 3; 7 → 4; 8 → 5; 9 → 6; 10 → 0; etc. This is your final answer.
In summary: day of week = (floor(T / 86400) + 4) mod 7.
(This assumes that you want the day of week in UTC. If you want to calculate it for another time zone, you need to perform some addition or subtraction of hours and minutes on T first.)
In JavaScript, days of the week are:
0 = Sun
1 = Mon
2 = Tue
3 = Wed
4 = Thu
5 = Fri
6 = Sat
You can use built-in methods:
// Unix epoch, 4 = Thu
new Date(0).getUTCDay()
// Today, 2 = Tue
new Date().getUTCDay()
Or a custom solution (remember to divide getTime() milliseconds by 1000):
// Unix epoch, 4 = Thu
(Math.floor(new Date(0).getTime() / 86400 / 1000) + 4) % 7
// Today, 2 = Tue
(Math.floor(new Date().getTime() / 86400 / 1000) + 4) % 7
Solution (from Geek for Geeks):
function dayOfWeek(d, m, y) {
let t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];
y -= (m < 3) ? 1 : 0;
return ( y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}
// Unix epoch, 4 = Thu
Math.floor(dayOfWeek(1, 1, 1970))
// Today, 2 = Tue
Math.floor(dayOfWeek(7, 12, 2021))
https://www.geeksforgeeks.org/find-day-of-the-week-for-a-given-date/

Encrypted timestamp 448 bit

I try to reverse engineer an GWT-API of a local public transport company (MVG in Munich). They don't offer a public REST-API or something similar. Unfortunately they use some sort of encrypted timestamps which consists of 7 letters. The alphabet is A-Za-z0-9$_ (in this order) which makes 64 different letters. One would need 6 bits to represent these 64 different letters.
So 7 letters * 6 bits/letter makes 42 bits.
I'm pretty sure that it is no bit field.
You can see it yourself on http://www.mvg-live.de/MvgLive/MvgLive.jsp#haltestelle=Am%20M%C3%BCnchner%20Tor&gehweg=0&zeilen=7&ubahn=true&bus=true&tram=true. Look out for (POST) requests to clockservice (http://www.mvg-live.de/MvgLive/mvglive/rpc/clockService, not working without using POST) which gives you the current server time.
Here are a few examples, with the date of the http-response:
UeEcvQB: Tue, 29 Jul 2014 23:27:15 GMT
UeGbS0O: Wed, 30 Jul 2014 08:40:13 GMT
UeGbhiJ: Wed, 30 Jul 2014 08:41:13 GMT
UeGozGI: Wed, 30 Jul 2014 09:39:13 GMT
UeGpBv$: Wed, 30 Jul 2014 09:40:13 GMT
Any help is appreciated. Thanks.
Looks to be the number of milliseconds after the Unix epoch (01/01/1970 00:00:00) converted to base-64 using that alphabet.
E.g.: UeGozGI can be converted back to decimal using:
U = 20
e = 30
G = 6
o = 40
z = 51
G = 6
I = 8
To decimal:
= (((((20 * 64 + 30) * 64 + 6) * 64 + 40) * 64 + 51) * 64 + 6) * 64 + 8
= 1406713147784
= 07/30/2014 09:39:07am
Which is (pretty close to) the time you indicates it encodes.

How can I parse a tab separated data file and group the extracted data in Perl?

I am newbie to Perl. I need to parse a tab separated text file. For example:
From name To name Timestamp Interaction
a b Dec 2 06:40:23 IST 2000 comment
c d Dec 1 10:40:23 IST 2001 like
e a Dec 1 16:03:01 IST 2000 follow
b c Dec 2 07:50:29 IST 2002 share
a c Dec 2 08:50:29 IST 2001 comment
c a Dec 11 12:40:23 IST 2008 like
e c Dec 2 07:50:29 IST 2000 like
c b Dec 11 12:40:23 IST 2008 follow
b a Dec 2 08:50:29 IST 2001 share
After parsing I need to create groups base upon users interaction. In this example
a<->b
b<->a
c<->a
a<->c
b<->c
c<->b
for this we can create one group. and we need to display list of groups.
I need some pointers on how to parse the file and form group?
Edit
Constraint-> at least 3 user required for creating group.
Interaction is nothing but some communication is done between two user. It does not matter of which communication
My Approach for solving is
We remove repeated interaction between users . such as "a<>b like "again if "a<>b follow" is present then we remove this row.
Creating 2 dimensional array which store interaction two users i.e
To Name a b c d
From Name
a X <> <> X
b <> X <> X
c <> <> X X
d X <> X X
X= Represent no interaction
<>= represent interaction
In this approach we start from first row i.e "a" user check with "b". if "a" is interact with "b" then we perform reverse of i.e "b" interact with "a". same steps perform for each column.
But this approach depends on number of users. If 1000 users are present then we have to create 1000 X 1000 matrix. IS there any alternative to solve this
I have added sample input
a c Dec 2 06:40:23 IST 2000 comment
f g Dec 2 06:40:23 IST 2009 like
c a Dec 2 06:40:23 IST 2009 like
g h Dec 2 06:40:23 IST 2008 like
a d Dec 2 06:40:23 IST 2008 like
r t Dec 2 06:40:23 IST 2007 share
d a Dec 2 06:40:23 IST 2007 share
t u Dec 2 06:40:23 IST 2006 follow
a e Dec 2 06:40:23 IST 2006 follow
k l Dec 2 06:40:23 IST 2009 like
e a Dec 2 06:40:23 IST 2009 like
j k Dec 2 06:40:23 IST 2003 like
c d Dec 2 06:40:23 IST 2003 like
l j Dec 2 06:40:23 IST 2002 like
d c Dec 2 06:40:23 IST 2002 like
m n Dec 2 06:40:23 IST 2005 like
c e Dec 2 06:40:23 IST 2005 like
m l Dec 2 06:40:23 IST 2011 like
e c Dec 2 06:40:23 IST 2011 like
h j Dec 2 06:40:23 IST 2010 like
d e Dec 2 06:40:23 IST 2010 like
o p Dec 2 06:40:23 IST 2009 like
e d Dec 2 06:40:23 IST 2009 like
p q Dec 2 06:40:23 IST 2000 comment
q p Dec 2 06:40:23 IST 2009 like
a p Dec 2 06:40:23 IST 2008 like
p a Dec 2 06:40:23 IST 2007 share
l p Dec 2 06:40:23 IST 2003 like
j l Dec 2 06:40:23 IST 2002 like
t r Dec 2 06:40:23 IST 2000 comment
r h Dec 2 06:40:23 IST 2009 like
j f Dec 2 06:40:23 IST 2008 like
g d Dec 2 06:40:23 IST 2007 share
w q Dec 2 06:40:23 IST 2003 like
o y Dec 2 06:40:23 IST 2002 like
x y Dec 2 06:40:23 IST 2000 comment
y x Dec 2 06:40:23 IST 2009 like
x z Dec 2 06:40:23 IST 2008 like
z x Dec 2 06:40:23 IST 2007 share
y z Dec 2 06:40:23 IST 2003 like
z y Dec 2 06:40:23 IST 2002 like
Output should be:
(a,c, d, e)
(x,y,z)
Parsing is easy. Just a split /\t/ might be enough. However, Text::xSV or Text::CSV might be better.
For the connections, you can use the Graph module. To be able to use that module effectively, you need to understand at least the basics of graph theory.
Note that a strongly connected component is defined as:
A directed graph is called strongly connected if there is a path from each vertex in the graph to every other vertex. In particular, this means paths in each direction; a path from a to b and also a path from b to a.
The strongly connected components of a directed graph G are its maximal strongly connected subgraphs.
However, note that if you have a <-> b and b <-> c, a, b, and c will form a strongly connected component meaning that is a weaker requirement than all members of a group interacted with each other in both directions.
We can still use this to reduce the search space. Once you have candidate groups, you can then check each to see if it fits your definition of a group. If a candidate group does not meet your requirements, then you can check all subsets with one fewer members. If you don't find any groups among those, you can then look at all subsets with two fewer members and so on until you hit the minimum group size limit.
The script below uses this idea. However, it very likely won't scale. I strongly suspect one might be able to put together some SQL magic but my mind is far too limited for that.
#!/usr/bin/env perl
use strict;
use warnings;
use Graph;
use Algorithm::ChooseSubsets;
use constant MIN_SIZE => 3;
my $interactions = Graph->new(
directed => 1,
);
while (my $interaction = <DATA>) {
last unless $interaction =~ /\S/;
my ($from, $to) = split ' ', $interaction, 3;
$interactions->add_edge($from, $to);
}
my #groups = map {
is_group($interactions, $_) ? $_
: check_subsets($interactions, $_)
} grep #$_ >= MIN_SIZE, $interactions->strongly_connected_components;
print "Groups: \n";
print "[ #$_ ]\n" for #groups;
sub check_subsets {
my ($graph, $candidate) = #_;
my #groups;
for my $size (reverse MIN_SIZE .. (#$candidate - 1)) {
my $subsets = Algorithm::ChooseSubsets->new(
set => $candidate,
size => $size,
);
my $groups_found;
while (my $subset = $subsets->next) {
if (is_group($interactions, $subset)) {
++$groups_found;
push #groups, $subset;
}
}
last if $groups_found;
}
return #groups;
}
sub is_group {
my ($graph, $candidate) = #_;
for my $member (#$candidate) {
for my $other (#$candidate) {
next if $member eq $other;
return unless $graph->has_edge($member, $other);
return unless $graph->has_edge($other, $member);
}
}
return 1;
}
__DATA__
a c Dec 2 06:40:23 IST 2000 comment
f g Dec 2 06:40:23 IST 2009 like
c a Dec 2 06:40:23 IST 2009 like
g h Dec 2 06:40:23 IST 2008 like
a d Dec 2 06:40:23 IST 2008 like
r t Dec 2 06:40:23 IST 2007 share
d a Dec 2 06:40:23 IST 2007 share
t u Dec 2 06:40:23 IST 2006 follow
a e Dec 2 06:40:23 IST 2006 follow
k l Dec 2 06:40:23 IST 2009 like
e a Dec 2 06:40:23 IST 2009 like
j k Dec 2 06:40:23 IST 2003 like
c d Dec 2 06:40:23 IST 2003 like
l j Dec 2 06:40:23 IST 2002 like
d c Dec 2 06:40:23 IST 2002 like
m n Dec 2 06:40:23 IST 2005 like
c e Dec 2 06:40:23 IST 2005 like
m l Dec 2 06:40:23 IST 2011 like
e c Dec 2 06:40:23 IST 2011 like
h j Dec 2 06:40:23 IST 2010 like
d e Dec 2 06:40:23 IST 2010 like
o p Dec 2 06:40:23 IST 2009 like
e d Dec 2 06:40:23 IST 2009 like
p q Dec 2 06:40:23 IST 2000 comment
q p Dec 2 06:40:23 IST 2009 like
a p Dec 2 06:40:23 IST 2008 like
p a Dec 2 06:40:23 IST 2007 share
l p Dec 2 06:40:23 IST 2003 like
j l Dec 2 06:40:23 IST 2002 like
t r Dec 2 06:40:23 IST 2000 comment
r h Dec 2 06:40:23 IST 2009 like
j f Dec 2 06:40:23 IST 2008 like
g d Dec 2 06:40:23 IST 2007 share
w q Dec 2 06:40:23 IST 2003 like
o y Dec 2 06:40:23 IST 2002 like
x y Dec 2 06:40:23 IST 2000 comment
y x Dec 2 06:40:23 IST 2009 like
x z Dec 2 06:40:23 IST 2008 like
z x Dec 2 06:40:23 IST 2007 share
y z Dec 2 06:40:23 IST 2003 like
z y Dec 2 06:40:23 IST 2002 like
Output:
Groups:
[ y z x ]
[ e d a c ]