Smelly Coding

ilan

Expert
Licensed User
Can you make this pice of code more sexy?

B4X:
public static int dayOfYear(int month, int dayOfMonth, int year) {
    if (month == 2) {
        dayOfMonth += 31;
    } else if (month == 3) {
        dayOfMonth += 59;
    } else if (month == 4) {
        dayOfMonth += 90;
    } else if (month == 5) {
        dayOfMonth += 31 + 28 + 31 + 30;
    } else if (month == 6) {
        dayOfMonth += 31 + 28 + 31 + 30 + 31;
    } else if (month == 7) {
        dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30;
    } else if (month == 8) {
        dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31;
    } else if (month == 9) {
        dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31;
    } else if (month == 10) {
        dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30;
    } else if (month == 11) {
        dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31;
    } else if (month == 12) {
        dayOfMonth += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 31;
    }
    return dayOfMonth;
}

should be possible to do with 3 lines ;) (at least thats the best i could do)
lets see your dry code :)

ps: a very nice article to read: https://ocw.mit.edu/ans7870/6/6.005/s16/classes/04-code-review/
 

Star-Dust

Expert
Licensed User
1.
B4X:
Public Sub dayOfYear (month As Int, dayOfMonth As Int,year As Int) As Int
    Dim Sum() As Int = Array As Int (0,0,31,59,90,120,151,181,212,243,273,304,334)
    Return dayOfMonth + Sum(month)
End Sub
2.
B4X:
Public Sub dayOfYear (month As Int, dayOfMonth As Int,year As Int) As Int
    Dim Sum() As Int = Array As Int (0,31, 28, 31, 30, 31, 30, 31, 31, 30,31, 30)
    For i=1 To month
        dayOfMonth = dayOfMonth + Sum(i)
    Next
    Return dayOfMonth
End Sub
 
Last edited:

JordiCP

Well-Known Member
Licensed User
My untested approach takes into account that November has 30days in Spain :D, and also leap years

B4X:
public static int dayOfYear(int month, int dayOfMonth, int year) {
   int mdays[] = {31, 28+((year&3)?0:1), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
   return( (month>1) ? ( dayOfYear( month-1, mdays[month-1] + dayOfMonth, year)) : dayOfMonth  );
}

I like Star-Dust's approach that avoids recursion :)
 

ilan

Expert
Licensed User
i must say that i am very surprised. both of you beat me with 2 lines :(

this was my code:

B4X:
public class Main {
    public static void main(String[] args) {
        System.out.println(getdayofyear(12,3,2000));
    }
    public static int getdayofyear(int day, int month, int year){
        int[] days = new int[]{31,28,31,30,31,30,31,31,30,31,30,31};
        //if (day > days[month-1]){System.out.println("you have entered a wrong value."); return 0;} //check if day is correct
        for (int i=0;i<month-1;i++){day += days[i];}
        //if (year > 1900 && year % 4 == 0){day += 1;} //calculate the leap year
        return day;
    }
}

how did i not think of doing it like this:

Public Sub dayOfYear (month As Int, dayOfMonth As Int,year As Int) As Int
Dim Sum() As Int = Array As Int (0,0,31,59,90,120,151,181,212,243,273,304,334)
Return dayOfMonth + Sum(month)
End Sub

???

really smart. and yours jordi is also really smart. can you please explain this sign ? in your code. what means ? inside the code?

public static int dayOfYear(int month, int dayOfMonth, int year) {
int mdays[] = {
31, 28+((year&3)?0:1), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
return( (month>1) ? ( dayOfYear( month-1, mdays[month-1] + dayOfMonth, year)) : dayOfMonth );
}
 

Star-Dust

Expert
Licensed User
i must say that i am very surprised. both of you beat me with 2 lines :(

this was my code:

B4X:
public class Main {
    public static void main(String[] args) {
        System.out.println(getdayofyear(12,3,2000));
    }
    public static int getdayofyear(int day, int month, int year){
        int[] days = new int[]{31,28,31,30,31,30,31,31,30,31,30,31};
        //if (day > days[month-1]){System.out.println("you have entered a wrong value."); return 0;} //check if day is correct
        for (int i=0;i<month-1;i++){day += days[i];}
        //if (year > 1900 && year % 4 == 0){day += 1;} //calculate the leap year
        return day;
    }
}

how did i not think of doing it like this:

code?
I have to thank my informatics teacher (of high school)
It was fixed with the code reduction (at the time the computers had little memory)
He spent many hours teaching us how to reduce the code and different methods, today they would not make sense because they would penalize the performance.

However, as an educational exercise, they are still valid

PS. We still did not talk about recursion. Only in the last year has started to present this topic
 

Star-Dust

Expert
Licensed User
for the calculation of the leap month
B4X:
Public Sub dayOfYear (month As Int, dayOfMonth As Int,year As Int) As Int
    Dim bissextile As Int  = 2*(0.5-Min((year Mod 4),0.5)+Min((year Mod 100),0.5)-Min((year Mod 400),0.5))
    Dim Sum() As Int = Array As Int (0,0,31,59,90,120,151,181,212,243,273,304,335)
 
    Return dayOfMonth + Sum(month) + (bissextile * Floor(Min(month,2)/2))
End Sub


(bissextile * Floor(Min(month,2)/2))
This code serves to add the leap day only if the month is February or later. If it were January (value 1) it would multiply the leap day by zero and then cancel it

2*(0.5-Min((year Mod 4),0.5)+Min((year Mod 100),0.5)-Min((year Mod 400),0.5))
We explain this second formula... Too complicated, try it and it works.
  1. Year 1985, it will be: 2 * (0.5-0.5+0.5-0.5) = 0
  2. Year 1900, it will be: 2 * (0.5-0.0+0.0 - 0.5) = 0
  3. Year 2004 it will be: 2 * (0.5-0.0+0.5 - 0.5) = 1
  4. Year 2000, it will be: 2 * (0.5+0.0- 0.0 - 0.0) = 1
PS: When I was studying informatics it was almost forbidden to use "IF" because they used too many machine cycles, so we were looking for other systems for calculation with the Mod and Div that we used less machine cycles and they were faster
 
Last edited:

Daestrum

Well-Known Member
Licensed User
A bit late but ( java 8+)
B4X:
 Dim localDate As JavaObject
 localDate.InitializeStatic("java.time.LocalDate")
 Log(localDate.RunMethodjo("of",Array(2019,12,31)).RunMethod("getDayOfYear",Null))

or shorter but harder to read
B4X:
Dim localDate as JavaObject
log(localDate.InitializeStatic("java.time.LocalDate").RunMethodJO("of",Array(2019,12,31)).RunMethod("getDayOfYear",null))
 
Last edited:

DonManfred

Expert
Licensed User

ilan

Expert
Licensed User

in b4x it would be like:

B4X:
if a>b then c else d

B4X:
Sub DayOfYear(Month As Int, DayOfMonth As Int, Year As Int) As Int
   Return DateTime.GetDayOfYear(DateUtils.SetDate(Year, Month, DayOfMonth))
End Sub

no cheating allowed :) the idea was to create a function to solve the problem without using external libs.
 

Star-Dust

Expert
Licensed User
I think that @ilan meant that the goal was to optimize the code of the post#1 and make it pleasant (he wrote sexy)
It is only an exercise, obviously with the available libraries it is not necessary to invent anything.

The link ilan posted placed the emphasis on the need to write code that is not only functional but is written in style. So I meant it as an exercise in style.
 
Last edited:

Sandman

Well-Known Member
Licensed User
Surely a little cheating is allowed? ;)

Ok, here's another version, without cheating. PHP this time - a oneliner:

B4X:
public function dayOfYear($month, $dayOfMonth)
{
    return [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 31][$month] + $dayOfMonth;
}

Thanks to very clever programming I was also able to remove the input year. ;)

Edit: Oh, I made a bug in there. Oh well, it happens - gonna leave it. :)
 
Last edited:

sorex

Expert
Licensed User
a lib less one liner based on @Star-Dust 's excellent (fixed) code...

I hope it fits the width of this forum ;)

B4X:
Public Sub dayOfYear (month As Int, dayOfMonth As Int,year As Int) As Int
    Return dayOfMonth+Bit.ParseInt(Regex.Split(",","0,0,31,59,90,120,151,181,212,243,273,304,335")(month),10)+2*(0.5-Min((year Mod 4),0.5)+Min((year Mod 100),0.5)-Min((year Mod 400),0.5))*Floor(Min(month,2)/2)
End Sub
 
Top