我有一个小问题 - 给出工作日的位掩码(例如,Sunday = 0x01, Monday = 0x02, Tuesday = 0x04
等等)和今天(以Sunday = 1, Monday = 2, Tuesday = 3
等形式...) - 从今天开始第二天发现的最优雅方式是什么?这是在位掩码中设置的?优雅我的意思是,如果没有if / switch / etc,有没有办法做到这一点...,因为我知道非优雅的方式?
编辑我可能应该提到(为了更清楚),持有位掩码的变量可以设置几天,例如(粗略地):
uDay = Sunday | Monday;
today = Tuesday;
我需要“星期天”
答案 0 :(得分:3)
int getNextDay(int days_mask, int today) {
if (!days_mask) return -1; // no days set
days_mask |= days_mask << 7; // duplicate days into next week
mask = 1 << (today % 7); // keep track of the day
while (!(mask & days_mask)) {
mask <<= 1;
++today;
}
return today % 7;
}
因此,如果在开始和循环时只有一个。怎么样?
编辑我刚刚意识到有一种退化的情况,即如果今天使用&gt; = 14(或大于最高位集),则while循环变为无限。第4行的(今天%7)修复了这种情况。
如果我可能(轻松地)对获得复选标记的其他版本抱怨,我的版本只有2个模数调用,而检查的解决方案将至少有1个模数调用和最多6个模数调用。
另外,如果今天设置的话,关于函数返回“今天”的评论很有意思。如果今天该函数不应该返回,除非今天是该集合中的唯一一天,则需要在我的解决方案的第3行预先增加。
答案 1 :(得分:2)
您根本不需要任何额外的变量。最简单的想法 - 从“明天”开始,看看连续几天,直到你在面具中找到一天 - 也是最优雅的实施。做得好的诀窍是把日子想象为星期日= 0,星期一= 1等等(仅在这个函数内)。然后,“今天”实际上是t-1
(其中t是函数的输入,因此从1到7),“明天”是(t-1+1)%7
,即t%7
等。
这很简单,并且已经针对litb的代码进行了详尽的测试,只是为了确保: - )
int getNextDay(int m, int t) {
if((m&127)==0) return t; //If no day is set, return today
t=t%7; //Start with tomorrow
while((m&(1<<t))==0) t = (t+1)%7; //Try successive days
return t+1; //Change back to Sunday=1, etc.
}
修改:如果您希望“下一个”表示“今天或更晚”,则“t = t%7”行应更改为t=t-1
或--t
。
答案 2 :(得分:1)
我这样理解你的问题:
// returns t (today) if no weekday is set in the mask.
int getNextDay(int m, int t) {
int i, idx;
for(i = 0, idx=t%7; i<7 && !((1<<idx)&m); i++, idx=(idx+1)%7)
/* body empty */ ;
return (i == 7) ? t : (idx + 1);
}
// getNextDay(8|2, 2) == 4, getNextDay(64, 2) == 7
// getNextDay(128, 2) == 2
答案 3 :(得分:1)
你打赌!这是否意味着任何通常意义上的“优雅”,嗯:我的意思是优雅,如果没有if / switch / etc,有没有办法做到这一点......
static unsigned next_day_set (unsigned today, unsigned set) {
unsigned arev = bitreverse (highest_bit_set (bitreverse ((set << 7) | set)
& (bitreverse (today) - 1)));
return ((arev >> 7) | arev) & 0x7f;
}
假设你有'优雅'的功能来反转一个字中的位并找到最左边的位集 - 见Hacker's Delight。如果你以相反的顺序表示工作日位,它会更简单,实际上甚至更真实,假设我没有搞砸:
enum {
Sunday = 1 << 6
Monday = 1 << 5
Tuesday = 1 << 4,
/* etc */
Saturday = 1 << 0
};
static unsigned next_day_set (unsigned today, unsigned set) {
unsigned a = highest_bit_set (((set << 7) | set) & ((today << 7) - 1));
return ((a >> 7) | a) & 0x7f;
}