text:
# Semroc My Boid

### Help Support The Rocketry Forum:

#### JAL3

##### Well-Known Member
I've had my Boid sitting around for a long while but had no real plans on building any time soon. After all, its pretty basic and had nothing to really pique my interest. I changed my mind, though, during a recent build of another rocket. There I tried using label paper to "seal" the balsa fins. While posting about it on TRF, I got some advice on how to do a better job of it and wanted to give the technique a try. The Boid seemed like the perfect victim for my learning experience.

#### JAL3

##### Well-Known Member
There are apparently several variants to the My Boid. My kit came with three balsa fins but the instructions indicate that there are also versions with 4 fins. The first step of the instructions is to determine which you have and then select the correct fin marking guide. I lined up the body tube one the 3 fin guide and then marked the aft end. An angle was used to extend the lines.

#### JAL3

##### Well-Known Member
The next step was to insert the engine hook in the precut slit. As I was doing this, the Kevlar harness had a loop put into one end and slipped around the hook.

#### JAL3

##### Well-Known Member
Instead of centering rings, this kit has more of a centering tube. It was slid over the engine hook and glued into place.

#### JAL3

##### Well-Known Member
The nosecone was one of the smoothest and nices pieces of balsa I have ever received. Instead of using regular filler, I decided to seal it with a layer of thin CA. It was drizzled on and allowed to soak into the wood then set aside to dry.

#### JAL3

##### Well-Known Member
As mentioned before, my Boid came with three balsa fins. They were in good shape and quickly removed from their parent material. I then sanded the leading edges round and tapered the trailing and outer edges.

#### JAL3

##### Well-Known Member
Next came the real purpose for this exercise. Previously, when I had used label paper to seal a fin, I would press the unsanded fin flat on the paper and then trim away the excess. I would then turn the fin over and do the same thing on the other side. Then I might, or might not, try to sand the desired profile into the fin.

This time, I took the sanded fin and laid it flat on the label paper. The fin was then "rolled" about its leading edge and pressed into the paper on the opposite side. This allowed the paper to follow the contour of the leading edge and provided for a much cleaner appearance. The label paper was then pressed flat against itself at all the other edges and a razor blade was used to trim away the excess.

It was not a perfect job but I think it will get better with practice and when I find my X-acto knife.

#### TheAviator

##### Well-Known Member
I was looking at the pictures of the motor mount, and was wondering if there was a motor block included. If there isn't, I would recommend putting one in. I've had rockets that, after a couple of flights, had the motor hook tear through the motor mount tube. I've only had this happen twice, and the motor has not completely flown through, but the rear end of the motor tube was singed and unusable. I've since beefed up the attachment of my hooks, but when weight is not an issue, I still add an engine block for added security.

Just think, most of the force of the engine is being transferred through that tiny little tab on the end of the motor hook, and by association, the glue joints holding the hook on. The steel doesn't always bond well, which causes this problem.

#### JAL3

##### Well-Known Member
I was looking at the pictures of the motor mount, and was wondering if there was a motor block included. If there isn't, I would recommend putting one in. I've had rockets that, after a couple of flights, had the motor hook tear through the motor mount tube. I've only had this happen twice, and the motor has not completely flown through, but the rear end of the motor tube was singed and unusable. I've since beefed up the attachment of my hooks, but when weight is not an issue, I still add an engine block for added security.

Just think, most of the force of the engine is being transferred through that tiny little tab on the end of the motor hook, and by association, the glue joints holding the hook on. The steel doesn't always bond well, which causes this problem.
While writing this up, I wracked my brain trying to remember if one had been installed. I have no specific memory of putting it in but that was a while back. Next time I'm at the shop I'm going to have to look and see if one is mentioned in the instructions and, if so, see if I have any extra pieces floating around.

I agree that that lack, if there is a lack, is a serious problem with longevity. I discovered that fairly early on with an Apogee Diamondback.

#### JAL3

##### Well-Known Member
The mounting of the motor mount into the airframe BT should have been a simple matter and it was. I managed to mess it up anyway. I was supposed to leave about 1/4" of the mount protruding from the end and I made the appropriate mark on the mount. I then swabbed some white glue inside the BT and inserted the mount. It was a tight fit and I really had to put some effort into the pushing. All of the sudden it moved...too far...and would not move again. My motor mount is usable but pushed in just a bit too far.

#### JAL3

##### Well-Known Member
As the motor mount glue continued to dry, I mounted the eyescrew in the nosecone and added a bit of white glue to the threads to make it hold better.

#### JAL3

##### Well-Known Member
In order to promote a stonger joint between the fins and the BT, I used a needle to poke a series of holes along the mounting line. I pricked a similar series of holes in the root edges of the fins. The fins were then glued in place using a double glue joint of white glue.

#### JAL3

##### Well-Known Member
As the glue on the fins set up, I also applied the launch lug flush with the aft end using white glue.

White glue fillets were applied to all the fin roots over the course of 2 days.

#### JAL3

##### Well-Known Member
All that was left of assembly was to tie the elastic to the Kevlar and then to the nose cone. It was an easy build.

#### JAL3

##### Well-Known Member
Finishing of My Boid began with a decision about what I wanted it to look like. I decided to try and keep things in the "bird" family and was wondering how to reconcile that with my lack of artistry. I looked over towards my paint shelves and saw blue and orange, two colors I seldom use. Then and there I decided that my My Boid was going to be called the Roadrunner, the mascot of my engineering school. (UTSA Roadrunners) The school colors are blue and orange and it seemed a simple enough idea.

I gave the rocket a gentle sanding, brushed it off and then sprayed on two coats of white primer. The primer was given 2 days to dry.

#### JAL3

##### Well-Known Member
When the 2 days were up, I gave the rocket a light sanding and then applied 2 coats of orange.

#### JAL3

##### Well-Known Member
The orange was given an opportunity to dry and then the fins and nose cone were masked so that the BT could be painted blue.

#### JAL3

##### Well-Known Member
It was then set up in the booth and given 2 coats of blue.

#### Buzzard

##### Well-Known Member
Great build threat, John. I got a "My Boid" kit when they first came out. Apparently each kit is a grab-bag of parts. Mine was a ST-8 tube with an elliptical nose cone and the FSI Competitor elliptical fins. It went together well and I went with an all-over red paint scheme. Flew it at a DARS launch on an A8-5 and it really scooted. In fact, most of the observers thought that it was flying on a B motor.
I purchased two more kits and they are buried in the build pile.

Chas

#### JAL3

##### Well-Known Member
Great build threat, John. I got a "My Boid" kit when they first came out. Apparently each kit is a grab-bag of parts. Mine was a ST-8 tube with an elliptical nose cone and the FSI Competitor elliptical fins. It went together well and I went with an all-over red paint scheme. Flew it at a DARS launch on an A8-5 and it really scooted. In fact, most of the observers thought that it was flying on a B motor.
I purchased two more kits and they are buried in the build pile.

Chas
Thanks for the kind words.

This really was one that I had no real attachment to. I just pulled it out to experiment with the paper on the fins. Having it turn out as well as it has is nice and has resulted on it growing on me a little bit. I've even going to get off my lazy backside and see if I can come up with some decals for it.

I didn't realize the grab bag nature of the kit. That explains a lot.

#### Buckaroo

##### Well-Known Member
We had a build session today with a group of about 15 4-H kids and used Boids from a bulk box. Excellent quality parts! The core of each rocket is the same, but the nose cone and fins are all different. There was one that had Cherokee-D fins/nose cone that was awesome, and I think the kids like the fact that their rocket is different than anyone else's in the room. Most of them are coming out to the Music City Missile Club launch this Sat so we'll see how well they hold up.

You can buy these by the 100 for $470 which is a steal given the quality of the kit. The only real drawback that I can see with this kit is that it comes with a standard Semroc 12" chute which is way more that this thing needs. A "C" motor and a little wind and it's gone. Good thing you can get em bulk By the way John thanks for the nice build thread. :clap: Last edited: #### JAL3 ##### Well-Known Member We had a build session today with a group of about 15 4-H kids and used Boids from a bulk box. Excellent quality parts! The core of each rocket is the same, but the nose cone and fins are all different. There was one that had Cherokee-D fins/nose cone that was awesome, and I think the kids like the fact that their rocket is different than anyone else's in the room. Most of them are coming out to the Music City Missile Club launch this Sat so we'll see how well they hold up. You can buy these by the 100 for$470 which is a steal given the quality of the kit.

The only real drawback that I can see with this kit is that it comes with a standard Semroc 12" chute which is way more that this thing needs. A "C" motor and a little wind and it's gone. Good thing you can get em bulk

By the way John thanks for the nice build thread. :clap:
I didn't know all this background on this bird, I mean boid. Thanks for the info and the kind words.

FWIW, mine did not come with a chute. It had a streamer instead.:neener:

#### JAL3

##### Well-Known Member
When the tape came off, it was looking good. The bleeds were insignificant and the colors worked together better than they ever did for UTSA. I decided to go ahead and try to make some decals.

#### Buckaroo

##### Well-Known Member
FWIW, mine did not come with a chute. It had a streamer instead.:neener:
Streamer makes more sense... I don't know the vintage of the bulk box we were using the other day,maybe they all come with streamer now, but then again you said you've had yours for a while so who knows? It's been raining hard all day/evening in Manchester, TN so I don't know if we'll see any Boids launched tomorrow.

The paint job looks nice John, I wouldn't have picked blue & orange to go together, but it seems to work. Good luck when it comes time to fly. I finally had to quit building min diameter (or near mid diameter) rockets, my eyes just couldn't keep track of them anymore, and I HATE losing rockets.

#### JAL3

##### Well-Known Member
Streamer makes more sense... I don't know the vintage of the bulk box we were using the other day,maybe they all come with streamer now, but then again you said you've had yours for a while so who knows? It's been raining hard all day/evening in Manchester, TN so I don't know if we'll see any Boids launched tomorrow.

The paint job looks nice John, I wouldn't have picked blue & orange to go together, but it seems to work. Good luck when it comes time to fly. I finally had to quit building min diameter (or near mid diameter) rockets, my eyes just couldn't keep track of them anymore, and I HATE losing rockets.
I would not have picked the combination either. I just happened to see these cans first when I was looking AND the "boid" connection to the UTSA Roadrunners hit me. That was my first engineering school and their colors are blue and orange.

I hate losing rockets too. For a while when I became a BAR, I was replacing almost everything with streamers.

#### JAL3

##### Well-Known Member
I located an image of the UTSA Roadrunner on the internet and downloaded it. Its different from what I remember.

#### JAL3

##### Well-Known Member
I opened the file in Photoshop and resized it to where I thought it would fit on the fins. I printed it out on a laser printer and found I was a bit too pessimistic on the size. From there, it was a simple matter of applying one decal to each side of each of the three fins. I also spaced three smaler ones around the nosecone.

#### JAL3

##### Well-Known Member
Its not fancy but I think the addition of a little decal dresses it up a bit. The rocket is ready for its maiden flight.

#### JAL3

##### Well-Known Member
My Boid was the first launch of the day when it went for its maiden flight. I loaded some dog barf and a 1/2A6-2 motor, mostly because I happened to have one sitting in front of me when I got through setting up the range. It took off nice and straight and, as expected, did not go very high. It probably could have coasted another second before ejection but all in all was a good maiden flight.

A video of the flight can be seen here: https://www.flickr.com/photos/[email protected]/3517002072/

#### JAL3

##### Well-Known Member
The second flight was nothign less than spectacular. I loaded an A6-4. I announced the flight and the rocket took off and kept going. I had announced it as an A6-4 but was accused by some of having loaded a B and by others a C. It went way up there. On retrieving it, I made sure the rocket was visible the whole time and made a production of removing the motor in front of witnesses. It was indeed an A6-4. It was also an impressive flight.

A short video of the flight can be seen here: https://www.flickr.com/photos/[email protected]/3517003644/

Its not very long because I cut it off when I lost sight of the rocket.


text:
# Sudoku Solver Class

This topic is 4023 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

This is just practice but I want to make sure it is cross platform and is over decent code, if you see anything wrong with it or something that should be made better let me know. MainFunctions.h
#ifndef MISCFUNCTIONS_H
#define MISCFUNCTIONS_H

#include <math.h>

int Power(int x, int y)
{
if( y > 0 )
return x *= Power(x, y-1);
else
return 1;
}

int CharToInt(char c)
{
if( c < '0' || c > '9' )
return -1;
else
return c - '0';
}

int StringToInt(char *str)
{
int number = 0;
int power = strlen(str) - 1;

for(int i = 0; i <= power; i++)
{
number += CharToInt(str) * Power(10, power - i);
}

return number;
}

int IntLen(int num)
{
return static_cast<int>( ceil( log10( static_cast<float>( num ) ) ) );
}

#endif

Sudoku.h
#ifndef SUDOKU_H
#define SUDOKU_H

#define SUCCESS 1
#define FAILED 0

#include <iostream>
#include <fstream>
#include <math.h>
#include "MiscFunctions.h"

using namespace std;

class Sudoku {

public:
Sudoku();
~Sudoku();

// Methods of sudoku matrix inputs
int ReadFile(const char* filePath);

// Fill in the blanks as much as possible without guessing
int Solve();

// Take 1 step toward solving
void Step();

int **matrix;
bool ***possible;
int size;

private:
// Scans all cells for numbers and marks that number
// in all cells of the same row, column, and 3x3 as not
// possible because it is already used.
int MarkNotPossible();

// Scans all cells and if there is only 1 possiblility
// then simply set that value to the corresponding
// matrix value.
int CheckForSinglePossibility();
};

Sudoku::Sudoku()
{
size = 1;
}

Sudoku::~Sudoku()
{
// Cleanup matrix
for(int i = 0; i < size; i++)
{
delete [] matrix;
}
delete [] matrix;

// Cleanup Possible array
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size; j++)
{
delete [] possible[j];
}
delete [] possible;
}
delete [] possible;
}

int Sudoku::ReadFile(const char* filePath)
{
// Flag
bool bSuccess = true;

ifstream file(filePath);

if( file.good() )
{
// Get the size of the sudoku matrix stored in the file
char c;
while( file.get(c) && c != '\n' )
{
if(c == ' ')
size++;
}

// Create the matrix array
matrix = new int*[size];
for(int i = 0; i < size; i++)
{
matrix = new int[size];
}

// Create the possible array
possible = new bool**[size];
for(int i = 0; i < size; i++)
{
possible = new bool*[size];
for(int j = 0; j < size; j++)
{
possible[j] = new bool[size];

for(int k = 0; k < size; k++)
{
possible[j][k] = 1;
}
}
}

//---------------------------------------------------------
// Extract string numbers from the file then convert
// them to int and store them
//
// -maxLength	max number of chars each value can use
// -ch			holds the current chacter to put in cc
// -cc			stores current value as a string
// -ccindex		index position of cc
// -pos			file cursor position
//---------------------------------------------------------
int maxLength = IntLen(size);
char ch;
char *cc = new char[maxLength];
int ccindex = 0;
int pos = 0;

for(int y = 0; y < size; y++)
{
for(int x = 0; x < size; x++)
{
file.seekg(pos);

while(	file.get(ch) && ch != ' ' && ch != '\n' && ccindex < maxLength)
{
cc[ccindex] = ch;
ccindex++;
pos++;
}

pos++;
ccindex = 0;

// Make sure the value is within range and store value
int value = StringToInt(cc);

if( value >= 0 && value <= size )
matrix[x][y] = value;
else
bSuccess = FAILED;

// Reset cc to null
for(int i = 0; i < maxLength; i++)
{
cc = '\0';
}
}

pos++;
}

delete [] cc;
}
else
bSuccess = FAILED;

file.close();

return bSuccess;
}

int Sudoku::Solve()
{
// Loop while one of these are making progress
while( MarkNotPossible() || CheckForSinglePossibility() ) {}

// If any cell is 0 then fail
for(int y = 0; y < size; y++)
{
for(int x = 0; x < size; x++)
{
if( matrix[x][y] == 0)
{
return FAILED;
}
}
}

return SUCCESS;
}

void Sudoku::Step()
{
MarkNotPossible();
CheckForSinglePossibility();
}

int Sudoku::MarkNotPossible()
{
bool bChanged = false;

for(int y = 0; y < size; y++)
{
for(int x = 0; x < size; x++)
{
if( matrix[x][y] > 0)
{
// Mark not possible for ROW (x)
for( int z = 0; z < size; z++ )
{
if( possible[z][y][matrix[x][y]-1] )
{
possible[z][y][matrix[x][y]-1] = false;
bChanged = true;
}

}

// Mark not possible for COLUMN (y)
for( int z = 0; z < size; z++ )
{
if( possible[x][z][matrix[x][y]-1] )
{
possible[x][z][matrix[x][y]-1] = false;
bChanged = true;
}
}

// Mark not possible for minisquare
float miniSize = float( sqrt(size) );

int ymin = int( floor(float(y)/miniSize) * miniSize );
int ymax = int( ceil(float(y)/miniSize) * miniSize );
if(ymax == ymin) ymax = ymin+int(miniSize);

int xmin = int( floor(float(x)/miniSize) * miniSize );
int xmax = int( ceil(float(x)/miniSize) * miniSize );
if(xmax == xmin) xmax = xmin+int(miniSize);

for(int Y = ymin; Y < ymax; Y++)
{
for(int X = xmin; X < xmax; X++)
{
if( possible[X][Y][matrix[x][y]-1] )
{
possible[X][Y][matrix[x][y]-1] = false;
bChanged = true;
}
}
}
}
}
}

return bChanged;
}

int Sudoku::CheckForSinglePossibility()
{
int possibleVal = 0;
int possibilities = 0;
bool bChanged = false;

// Find a cell with only 1 possibility and adjust matrix value
for(int y = 0; y < size; y++)
{
for(int x = 0; x < size; x++)
{
if(matrix[x][y] == 0)
{
for(int z = 0; z < size; z++)
{
if( possible[x][y][z] == true )
{
possibleVal = z;
possibilities++;
}
}

if(possibilities == 1)
{
bChanged = true;
matrix[x][y] = possibleVal + 1;
}
}

possibilities = 0;
}
}

return bChanged;
}

#endif

##### Share on other sites
Alright, a few suggestions. (Mainly because the code formatting got things messed up, and I also don't have time to understand the code completely).

You have a lot of memory allocation and C strings. Why not replace your arrays with a safer vector, and char*'s with std::string?

int CharToInt(char c)

There's a lovely function in C called isdigit that will determine if your character is a numeral. Then you could just cast it to the number. While technically not faster, using premade functions that already exist can help clean up code. Other functions such as StringToInt would also disappear this way too.

I'd also probably break up Sodoku into a header and cpp file. Just for readability sake. And for clarification (due mainly to time limitations on my part), how are you solving the puzzle? Brute force? Algorithm? etc.

##### Share on other sites
Quote:
 You have a lot of memory allocation and C strings. Why not replace your arrays with a safer vector, and char*'s with std::string?

I will look into vectors and strings, my strings and arrays are really simple so Im not sure if larger things are needed.

Quote:
 There's a lovely function in C called isdigit that will determine if your character is a numeral. Then you could just cast it to the number. While technically not faster, using premade functions that already exist can help clean up code. Other functions such as StringToInt would also disappear this way too.

Ill look into cleaning this up, found atoi function that converts an char to an int.

Quote:
 I'd also probably break up Sodoku into a header and cpp file. Just for readability sake.

I usually do this but I wanted to release it as a little Sudoku ?library? and thought it would easier to handle and stuff if it were a simple .h

Quote:
 And for clarification (due mainly to time limitations on my part), how are you solving the puzzle? Brute force? Algorithm? etc.

There are two functions:
// Scans all cells for numbers and marks that number
// in all cells of the same row, column, and 3x3 as not
// possible because it is already used.
int MarkNotPossible();

// Scans all cells and if there is only 1 possiblility
// then simply set that value to the corresponding
// matrix value.
int CheckForSinglePossibility();

They are called in that order until both of them return 0 meaning they made no progress. If they dont make progress, that means it is solved or the solution requires guessing.

Now I have tried to add multi-threading support to speed up the solving but I failed using pthread. I had the thinking I could have one thread run MarkNotPossible() while the other ran CheckForSinglePossibility() until it was solved. Any ideas or maybe a link to some good multi-threading tutorials?

##### Share on other sites
I looked into this over a year ago when sudoku first came to my attention and found another C based solver. I can't remember where I found it unfortunately, but it had a nice feature that you could implement.

It created a move tree with the different options available at any time. If a move led to the Sudoku not being solvable it would step back to the last decision point and try the next option. That will lead to a nicer solver.

##### Share on other sites
Well to clarify the code for the minisquares you might want to use modulo.

int ymin = y - (y % miniSize);
int ymax = y + (miniSize - (y % miniSize));

ok, is not that much of an improvement; but atleast you stay in the ints... you might wrap that in a function call like

int ymin = get_square_min(y);
int ymax = get_square_max(y);

Following the idea of of readable code.

Your code is ok. You might want to pack the single parts into functions / methods. It all goes to the idea of readabe code; which is worth gold.

Here a litle example
for (int x = 0; x &tl size; x++) {
for (int y = 0; y < size; y++) {
if (is_empty_cell(x,y)) {
mark_horizontal_column(x,y);
mark_vertical_column(x,y);
mark_square(x,y);
}
}
}

You aproach is a deph search aproach wich gets you stuck on some cases. Thought about backtracking? Since what is a solver good for if it gets stuck?

Ok, you might know that backtracking has square complexity; how about solving sodoku with a more generic aproach like simulated anealing. Or an optimized graph search like a*.

Just getting you into some ideas, to show that there are more solutions to solving a problem than the algorithmic one.

I have noticed that you do alot of duplicate work, that is you look at all cells and mark all non possible values. There is a simple solution to combining marking cadidates and filling cells.

1. Scan the field and mark candidats that are not posible. Evey time you mark a cell that drops to on candiate you put it in a list.
2 For all cells in the list of one candidate you set the value and mark the all cells afected, while marking you continue to fill the list with single candidates.

The clue is that you combine the setting of the value of a cell with marking and marking of cells with gathering single values.

If you keep a list of cells with two candidates, once the list for one is depeleted, you store the state on a stack and guess one value. If you do not find a solution, pop the old state of the stack and use the other value. This will keep you going quite far.

##### Share on other sites
Quote:
 Original post by JYI looked into this over a year ago when sudoku first came to my attention and found another C based solver. I can't remember where I found it unfortunately, but it had a nice feature that you could implement.It created a move tree with the different options available at any time. If a move led to the Sudoku not being solvable it would step back to the last decision point and try the next option. That will lead to a nicer solver.

If I understand what you mean, this one actually does that, the multi-dimentional possible array is an array of booleans that mark all possible numbers for each spot, maybe I will make an OpenGL demo of this so you could see what it is doing behind the scenes. :)

Quote:
 Original post by Anonymous PosterWell to clarify the code for the minisquares you might want to use modulo.int ymin = y - (y % miniSize);int ymax = y + (miniSize - (y % miniSize));ok, is not that much of an improvement; but atleast you stay in the ints... you might wrap that in a function call likeint ymin = get_square_min(y);int ymax = get_square_max(y);Following the idea of of readable code.Your code is ok. You might want to pack the single parts into functions / methods. It all goes to the idea of readabe code; which is worth gold.Here a litle examplefor (int x = 0; x &tl size; x++) { for (int y = 0; y < size; y++) { if (is_empty_cell(x,y)) { mark_horizontal_column(x,y); mark_vertical_column(x,y); mark_square(x,y); } }}You aproach is a deph search aproach wich gets you stuck on some cases. Thought about backtracking? Since what is a solver good for if it gets stuck?Ok, you might know that backtracking has square complexity; how about solving sodoku with a more generic aproach like simulated anealing. Or an optimized graph search like a*. Just getting you into some ideas, to show that there are more solutions to solving a problem than the algorithmic one.I have noticed that you do alot of duplicate work, that is you look at all cells and mark all non possible values. There is a simple solution to combining marking cadidates and filling cells.1. Scan the field and mark candidats that are not posible. Evey time you mark a cell that drops to on candiate you put it in a list.2 For all cells in the list of one candidate you set the value and mark the all cells afected, while marking you continue to fill the list with single candidates.The clue is that you combine the setting of the value of a cell with marking and marking of cells with gathering single values.If you keep a list of cells with two candidates, once the list for one is depeleted, you store the state on a stack and guess one value. If you do not find a solution, pop the old state of the stack and use the other value. This will keep you going quite far.

Great info, I will go over it and see what I can do.

##### Share on other sites
Your solution method will not work on all valid boards. There are situations where all the empty cells can have more than one possible value. This doesn't necessarily mean that there is more than one solution (ie an invalid board) because choosing the wrong value to place in a cell will eventually lead to a situation where there are no valid values to place in a cell. In situations like this, taking a guess and then backtracking later if a conflict appears is the usual solution.

The only time you know that a board has no solution is when it inevitably leads to a cell having no possible values. Otherwise there is still a chance to find a solution by filling in an arbitrary value. You only know that a board has more than one solution if you actually find more than one solution (or mathematically prove that somehow, but I don't think we want to get into that).

##### Share on other sites
Quote:
 Original post by MVPThis is just practice but I want to make sure it is cross platform and is over decent code, if you see anything wrong with it or something that should be made better let me know.MainFunctions.h*** Source Snippet Removed ***Sudoku.h*** Source Snippet Removed ***

I took a quick glance and one thing I would change, and admittedly this isn't an important change, is that Power(int,int) function to use iteration instead of recursion.

int Power(int x,int y){  int ret=1;  for (int i=0;i<y;i++)    ret*=x;  return ret;}

I just think it's generally better to avoid recursion when possible because it can easily lead to blowing the stack. Although in this case the problem of integer overload will likely crop up before that..

##### Share on other sites
Ive made quite a bit of progress, optmized a lot.

In a for loop would you guys use char? I dont really need 4 byte int to do them so I could probably get away with char. I.E. for(char i = 0; i < x; i++) or unsigned char even.

What are your thoughts?

##### Share on other sites
In any practical situation, what, exactly, do you think you would gain by using a char as loop variable instead of an int?

##### Share on other sites
It would use less memory.

##### Share on other sites
Well the solution involves guessing and backtracking, so actually it will solve all possible (valid) boards. The idea is to get a solution that involves no searching for a candidate, since that always involves at least square complexity. The point for the two list, is a to keep a list of possible candidates for for the guessing. The solution will get about 3/4 of all possible sodoku boards. And I have never seen any boards where the guess took more than two candidates. But the heuristic behind the guess is that the best candidate for a guess is the one with the few possible candidates.

P.S. I am actually cheating... We had to solve the problem in a "computational intelligence" course

P.P.S I am the anonymous poster, had not noticed that I was not logged on.

P.P.P.S sorry about that double post...

##### Share on other sites
rioki, did you look at the code that was posted? I didn't see any backtracking in there. If I missed it, could someone point out where it is?

Using a char instead of an int is a really low level micro-optimization. You're not really saving any significant amount of memory, and unless you're profiling your code you really have no way of knowing if it makes the code run faster or slower. If it did make the code run faster, it would be by an extremely small amount. As long as you know it won't overflow, it can't hurt I guess. But you're not really gaining much.

##### Share on other sites
Quote:
 Original post by MVPIt would use less memory.

Really? What about alignment issues? Variables around your loop index may have to be placed on a 32-bit alignment (or something other than 8-bit alignment) anyway, leaving your loop variable with a number of bytes padding wasted memory. Nothing saved.

Besides, I can see you allocate arrays with several levels of pointers and allocations. Way more than all loop variables combined. Saving loop variables is nothing compared to that. Save where it matters, and loop variables is not that place.

[Edited by - Brother Bob on February 2, 2007 6:11:32 AM]

##### Share on other sites
Quote:
 Original post by MVPIt would use less memory.

You should be aware that anything smaller than an int is very likely to be optimized to int.

In the IA-32 architecture, if the data on the stack is not 4 byte aligned then you incur an extra IO cycle when popping and pushing from the stack. Sure, in this example it's an irrelevance, but it's worthwhile being aware of it.

##### Share on other sites
Small update, I just cleaned it up a little bit, still need to add guessing functionality.

Link to the Code Blocks Project File: Sudoku Solver

Main.cpp
#include <iostream>using namespace std;#include "Sudoku.h"#include <windows.h>double GetMicroTime(){	LARGE_INTEGER ticks, ticksPerSecond;	QueryPerformanceFrequency(&ticksPerSecond);	QueryPerformanceCounter(&ticks);	return ( double(ticks.QuadPart) / double(ticksPerSecond.QuadPart) );}void PrintSudoku(Sudoku *sud){	for(int y = 0; y < sud->GetSize(); y++)	{		for(int x = 0; x < sud->GetSize(); x++)		{			if( sud->GetMatrixElement(x, y) < 10)				cout << " ";			cout << sud->GetMatrixElement(x, y) << " ";		}		cout << endl;	}}int main(){	double time1 = 0.0, time2 = 0.0;	Sudoku sud;	char fileName[64];	cout << "Open File: ";	cin >> fileName;	time1 = GetMicroTime();	if( sud.ReadFile(fileName) )	{		time2 = GetMicroTime();		cout << "ReadFile: " << (time2 - time1)*1000.0 << " ms" << endl << endl;		PrintSudoku(&sud);		cout << endl;		time1 = GetMicroTime();		// START TIMING		sud.Solve();		// END TIMING		time2 = GetMicroTime();		PrintSudoku(&sud);		cout << endl << "Solve: " << (time2 - time1)*1000.0 << " ms" << endl << endl;	}	else		cout << "Failed to read file." << endl;	system("PAUSE");	return 0;}

Sudoku.h
#ifndef SUDOKU_H#define SUDOKU_H#include <fstream>using namespace std;class Sudoku {public:	Sudoku();	~Sudoku();	// Methods of sudoku matrix inputs	int ReadFile(const char* filePath);	// Scans all cells for numbers and marks that number	// in all cells of the same row, column, and 3x3 as not	// possible because it is already used.	int MarkNotPossible();	// Scans all cells and if there is only 1 possiblility	// then simply set that value to the corresponding	// matrix value.	int CheckForSinglePossibility();	// Fill in the blanks as much as possible without guessing	int Solve();	// Check if the sudoku has been solved	bool IsSolved();	// Take 1 step toward solving	void Step();	// Accessor functions	int GetSize() { return size; }	int GetMatrixElement(int x, int y) { return matrix[x][y]; }private:	int **matrix;	int size;	bool ***possible;	bool readSuccessful;	void CreateMatrixAndPossibilityArray(int size);	void DeleteMatrixAndPossibilityArray();	bool MarkNotPossible_Row(int x, int y);	bool MarkNotPossible_Column(int x, int y);	bool MarkNotPossible_MiniSquare(int x, int y);	void SetSize( ifstream *file );};#endif

Sudoku.cpp
#include "Sudoku.h"#include "MiscFunctions.h"#include <iostream>using namespace std;Sudoku::Sudoku(){	size = 1;	readSuccessful = false;}Sudoku::~Sudoku(){	DeleteMatrixAndPossibilityArray();}int Sudoku::ReadFile(const char* filePath){	bool bSuccess = true;	// Open File	ifstream file(filePath);	// If path given doesnt link to a file	if(!file.good())		return false;	SetSize(&file);	CreateMatrixAndPossibilityArray(size);	int maxLength = IntLen(size);	// Get File Length	file.seekg (0, ios::end);	int fileLen = file.tellg();	file.seekg (0, ios::beg);	// Create array to store the file contents in	char *fileArray = new char[fileLen];	for(int i = 0; i < fileLen; i++)	{		file.get( fileArray);	}	// File inside of array now so close the file	file.close();	// Parse the fileArray for number sections and place them int the matrix array	char *curNumAsStr = new char[maxLength];	int curNumAsStrIndex = 0;	int matrixIndex = 0;	for(int i = 0; i < fileLen; i++)	{		if(fileArray >= '0' && fileArray <= '9')		{			curNumAsStr[curNumAsStrIndex] = fileArray;			curNumAsStrIndex++;		}		else if(curNumAsStrIndex && (fileArray == ' ' || fileArray == '\n'|| i == fileLen-1))		{			matrix[matrixIndex%size][matrixIndex/size] = StringToInt(curNumAsStr);			matrixIndex++;			curNumAsStrIndex = 0;			// Unset curNumAsStr			for(int j = 0; j < maxLength; j++)				curNumAsStr[j] = '\0';		}	}	delete [] curNumAsStr;	delete [] fileArray;	readSuccessful = bSuccess;	return bSuccess;}int Sudoku::MarkNotPossible(){	bool bChanged = false;	for(int y = 0; y < size; y++)	{		for(int x = 0; x < size; x++)		{			if( matrix[x][y] > 0)			{				// MarkNotPossible functions return true if				// they changed the possibility array				if(	MarkNotPossible_Row(x, y) ||					MarkNotPossible_Column(x, y) ||					MarkNotPossible_MiniSquare(x, y) )				{					bChanged = true;				}			}		}	}	return bChanged;}int Sudoku::CheckForSinglePossibility(){	int possibleVal = 0;	int possibilities = 0;	bool bChanged = false;	// Find a cell with only 1 possibility and adjust matrix value	for(int y = 0; y < size; y++)	{		for(int x = 0; x < size; x++)		{			if(matrix[x][y] == 0)			{				for(int z = 0; z < size; z++)				{					if( possible[x][y][z] == true )					{						possibleVal = z;						possibilities++;					}				}				if(possibilities == 1)				{					bChanged = true;					matrix[x][y] = possibleVal + 1;				}			}			possibilities = 0;		}	}	return bChanged;}int Sudoku::Solve(){	// Loop while one of these are making progress	while( MarkNotPossible() || CheckForSinglePossibility() ) {}	return IsSolved();}bool Sudoku::IsSolved(){	// If any cell is 0 then fail	for(int y = 0; y < size; y++)	{		for(int x = 0; x < size; x++)		{			if( matrix[x][y] == 0)			{				return false;			}		}	}	return true;}void Sudoku::Step(){	MarkNotPossible();	CheckForSinglePossibility();}void Sudoku::CreateMatrixAndPossibilityArray(int size){	// Create the matrix array	matrix = new int*[size];	for(int i = 0; i < size; i++)	{		matrix = new int[size];		for(int j = 0; j < size; j++)		{			matrix[j] = 0;		}	}	// Create the possible array	possible = new bool**[size];	for(int i = 0; i < size; i++)	{		possible = new bool*[size];		for(int j = 0; j < size; j++)		{			possible[j] = new bool[size];			for(int k = 0; k < size; k++)			{				possible[j][k] = 1;			}		}	}}void Sudoku::DeleteMatrixAndPossibilityArray(){	if( readSuccessful )	{		// Cleanup matrix		for(int i = 0; i < size; i++)		{			delete [] matrix;		}		delete [] matrix;		// Cleanup Possible array		for(int i = 0; i < size; i++)		{			for(int j = 0; j < size; j++)			{				delete [] possible[j];			}			delete [] possible;		}		delete [] possible;	}}bool Sudoku::MarkNotPossible_Row(int x, int y){	bool bChanged = false;	// Mark not possible for ROW (x)	for( int z = 0; z < size; z++ )	{		if( possible[z][y][matrix[x][y]-1] )		{			possible[z][y][matrix[x][y]-1] = false;			bChanged = true;		}	}	return bChanged;}bool Sudoku::MarkNotPossible_Column(int x, int y){	bool bChanged = false;	// Mark not possible for COLUMN (y)	for( int z = 0; z < size; z++ )	{		if( possible[x][z][matrix[x][y]-1] )		{			possible[x][z][matrix[x][y]-1] = false;			bChanged = true;		}	}	return bChanged;}bool Sudoku::MarkNotPossible_MiniSquare(int x, int y){	bool bChanged = false;	// Mark not possible for minisquare	int miniSize = int(sqrt(size));	int ymin = y - (y % miniSize);	int ymax = y + (miniSize - (y % miniSize));	int xmin = x - (x % miniSize);	int xmax = x + (miniSize - (x % miniSize));	for(int Y = ymin; Y < ymax; Y++)	{		for(int X = xmin; X < xmax; X++)		{			if( possible[X][Y][matrix[x][y]-1] )			{				possible[X][Y][matrix[x][y]-1] = false;				bChanged = true;			}		}	}	return bChanged;}// Set the size of the sudoku matrix stored in the filevoid Sudoku::SetSize( ifstream *file ){	char c;	while( file->get(c) && c != '\n' )	{		if(c == ' ')			size++;	}}

MiscFunctions.h
#ifndef MISCFUNCTIONS_H#define MISCFUNCTIONS_H#include <math.h>#include <iostream>using namespace std;int Power(int x, int y){	int ret = 1;	for(int i = 0; i < y; i++)	{		ret *= x;	}	return ret;}int CharToInt(char c){	if( c < '0' || c > '9' )		return -1;	else		return c - '0';}int StringToInt(char *str){	int number = 0;	int power = strlen(str) - 1;	for(int i = 0; i <= power; i++)	{ 		number += CharToInt(str) * Power(10, power - i);	}	return number;}int IntLen(int num){	return static_cast<int>( ceil( log10( static_cast<float>( num ) ) ) );}#endif

##### Share on other sites
You moved the function implementations in Soduku.h to Soduku.cpp. That's excellent, but you also need to do that for the functions in MiscFunctions.h
Quote:
 Original post by MVPIt would use less memory.

Honestly, saving 3 bytes of memory on a machine with over a billion bytes of memory* is not worth the millisecond you spent considering it. That is an example of micro-optimization at its worst. Avoid optimizing your code for now, it will only lead to hard-to-solve problems.

* Actually, in this case the compiler is likely to keep the variable in a register regardless of the size, so you have saved no memory at all.

##### Share on other sites
Thanks. :) I split MiscFunctions.h up. Im going to be looking into algorithms now, I haven't done any complex ones before so Im not sure where to start for the guessing stuff. If you know of any awesome resources for this one I would love a link so I can take a gander. :)

Thanks again. :)

##### Share on other sites
Oh boy.

Sorry to say, this is still pretty awful. I haven't had a chance to test anything, cut it up properly into files or write out my explanations of what's wrong coherently, yet; but for now you can go over my notes:

- bizarre file parsing: requires whitespace to separate numbers even though it calculates a "max length" for them - can only generate overflows. No null terminator anyway!- Hungarian notation on booleans. Also, return bool FFS!- But never mind that, because the correct approach is to read the data in in the constructor, and throw an exception on failure. Also, storing 'readSuccessful' internally is no use because it isn't checked except to clean up (hint: deleting a null pointer is fine).- Use the standard library.- You don't need to comment things like "open the file"; see the other thread.- Data layout. There should be a separate class to represent individual cells. Having done that, we can organize the algorithm properly, and also see that the 'value' property of a cell is redundant and can be calculated from the possibilities array.- fstream include goes in Sudoku.cpp, not .h. And never 'using namespace std' in a header!!!- PrintSudoku is Sudoku class functionality. Also the formatting is not very general.- Public interface of Sudoku should only have the solve and print functionality.- Time conversion is the wrong way around.- endl abuse.- Don't artificially pause programs at the end!!!Keep scrolling for improved-source-in-progress...#include <iostream>using namespace std;#include "Sudoku.h"#include <windows.h>double GetMicroTime() {	LARGE_INTEGER ticks, ticksPerSecond;	QueryPerformanceFrequency(&ticksPerSecond);	QueryPerformanceCounter(&ticks);	return ( double(ticks.QuadPart) / double(ticksPerSecond.QuadPart) );}int main() {	std::string fileName;	cout << "Open File: ";	cin >> fileName;	try {		double time = GetMicroTime();		Sudoku s(fileName);		cout << "ReadFile: " << (GetMicroTime() - time1) / 1000.0 << " ms\n\n" << s << endl;		time = GetMicroTime();		s.solve();		time = GetMicroTime() - time;		cout << s << "\nSolve: " << time / 1000.0 << " ms\n" << endl;	} catch (std::exception& ex) {		cout << "Oops, something went wrong: " << ex.what() << endl;	}}#ifndef SUDOKU_H#define SUDOKU_Hconst int UNKNOWN_CELL = 0;const int IMPOSSIBLE_CELL = -1; // a logical contradiction was found.class Cell {	public:	Cell(int value, int max) : possibilities(new bool[max]) {		for (int i = 0; i < max; ++i) {			possibilities = (i + 1 == value) || (value == UNKNOWN_CELL);		}	}	~Cell() { delete[] possibilities; }	bool removePossibility(int value) {		if (possibilities[value - 1]) {			possibilities[value - 1] = false;			return true;		}		return false;	}	bool known() {		int v = value();		return v != IMPOSSIBLE_CELL && v != UNKNOWN_CELL;	}	int value() {		int result = IMPOSSIBLE_CELL;		for (int i = 0; i < max; ++i) {			if (possibilities) {				result = (result == IMPOSSIBLE_CELL) ? (i + 1) : UNKNOWN_CELL;			}		}		return result;	}	private:	bool* possibilities;	Cell(const Cell&);	Cell& operator=(const Cell&);};class Sudoku {	public:	Sudoku();	// Fill in the blanks as much as possible without guessing	bool solve();	// Check if the sudoku has been solved	bool isSolved();	// Take 1 step toward solving	void reduce();	friend ostream& operator<<(ostream& os, const Sudoku& s);	private:	vector<Cell> matrix;	int size;	int mini_size;	Cell& at(int x, int y) {		return matrix[y * size + x];	}	bool reduce_row(int x, int y, int value);	bool reduce_column(int x, int y, int value);	bool reduce_minisquare(int x, int y, int value);};#endif#include "Sudoku.h"#include <iostream>#include <fstream>using namespace std;ostream& operator<<(ostream& os, const Sudoku& s) {	// Figure out how wide the numbers may be.	stringstream ss;	ss << s.size;	int width = ss.str().size();	for (int y = 0; y < s.size; y++) {		for (int x = 0; x < s.size; x++) {			os << setwidth(width);			int value = s.at(x, y).value();			switch(value) {				case UNKNOWN_CELL: os << "?"; break;				case IMPOSSIBLE_CELL: os << "X"; break;				default: os << value;			}		}		os << '\n';	}	return os;}void Sudoku::appendFileLineToData(const std::string& line, std::vector<int>& data) {	std::stringstream parser(line);	int value;	while (parser >> value) {		data.push_back(value);	}}Sudoku::Sudoku(const std::string& filePath) {	ifstream file(filePath.c_str());	// Since we're going to throw an exception for any unexpected file failure,	// we can just let the file object do that for us:	file.exceptions();	vector<int> data;	// Read the first line and deduce the sudoku size.	std::string line;	std::getline(file, line);	appendFileLineToData(line, data);	size = data.size();	// Make sure this is a valid size	mini_size = sqrt(size);	if (size != mini_size * mini_size) {		stringstream error_message("");		error_message << size << " is not a valid sudoku size (must be a square number)\n";		throw std::runtime_error(error_message);	}	// Now read all the rest of the lines.	data.reserve(size * size);	// This is an unusual way of numbering the lines, but it's convenient here.	for (int i = 2; i <= size; ++i) {		std::getline(file, line);		appendFileLineToData(line, data);		if (data.size() != size * i) {			stringstream error_message("");			error_message << "Incorrect number of elements on line " << i << "(expected " << size << ", got " << data.size() - size * (i - 1) << ")\n";			throw std::runtime_error(error_message);		}	}	// Finally we can convert the numbers into Cell objects.	matrix.reserve(size * size);	for (int i = 0; i < size * size; ++i) {		matrix = Cell(data, size);	}}int Sudoku::reduce() {	bool changed = false;	for (int y = 0; y < size; y++) {		for (int x = 0; x < size; x++) {			if (at(x, y).known()) {				int value = at(x, y).value();				if (reduce_row(x, y, value) ||				    reduce_column(x, y, value) ||				    reduce_minisquare(x, y, value)) {					changed = true;				}			}		}	}	return changed;}bool Sudoku::solve() {	while (reduce());	return IsSolved();}bool Sudoku::isSolved() {	for (int y = 0; y < size; y++) {		for (int x = 0; x < size; x++) {			if (!at(x, y).known()) {				return false;			}		}	}	return true;}bool Sudoku::reduce_row(int x, int y, int value) {	bool changed = false;	for (int z = 0; z < size; z++) {		if (at(z, y).removePossibility(value)) {			changed = true;		}	}	return changed;}bool Sudoku::reduce_column(int x, int y, int value) {	bool changed = false;	for (int z = 0; z < size; z++) {		if (at(x, z).removePossibility(value)) {			changed = true;		}	}	return changed;}bool Sudoku::reduce_minisquare(int x, int y, int value) {	bool changed = false;	int ymin = (y / mini_size) * mini_size;	int xmin = (x / mini_size) * mini_size;	for (int j = ymin; j < ymin + mini_size; ++j) {		for (int i = xmin; i < xmin + mini_size; ++i) {			if (at(i, j).removePossibility(value)) {				changed = true;			}		}	}	return changed;}

I pretty much had to rewrite the file parsing from scratch, because the current approach is a dead end. You'll notice the misc functions are *completely gone*. I won't even bother to go into detail about how the power() algorithm can be made faster for large powers, or how it's wasteful to exponentiate each digit instead of just iteratively "multiplying and accumulating"; because it's not important - manually converting integers to strings is, in a desktop environment, a fool's task.

##### Share on other sites
Oh wow, some great ideas. I am definetly going to be going through that later. Thanks a lot. Rating++ :)

format: plain


text:
# What is an electron configuration of a nitrogen molecule?

Aug 24, 2016

The electron configuration of ${\text{N}}_{2}$ is
(σ1s)^2(σ^"∗"1s)^2(σ2s)^2(σ^"∗"2s)^2(π2p_x)^2(π2p_y)^2(σ2p_z)^2

#### Explanation:

The molecular orbitals of ${\text{N}}_{2}$ are formed by overlapping the atomic orbitals of the $\text{N}$ atoms.

The new molecular orbitals are formed as follows:

• The $1 s$ orbitals form a bonding σ1s and an antibonding σ"*"1s MO.
• The $2 s$ orbitals form a bonding σ2s and an antibonding σ"*"2s MO.
• The $2 p$ orbitals directed along the internuclear axis form a bonding σ2p_z and an antibonding σ"*"2p_z MO.
• The $2 {p}_{x}$ and $2 {p}_{y}$ orbitals from each atom form bonding π2p_x and π2p_y bonding MOs and antibonding π"*"2p_x and π"*"2p_y MO.

The relative energy levels of the orbitals are

Each $\text{N}$ atom contributes seven electrons, so we use the Aufbau Principle to fill the MOs starting at the lowest level.

The result is

Thus, the electron configuration of ${\text{N}}_{2}$ is

(σ1s)^2(σ^"∗"1s)^2(σ2s)^2(σ^"∗"2s)^2(π2p_x)^2(π2p_y)^2(σ2p_x)^2


text:
# System of Coupled Differential Equations

I'm not sure if I'm using the correct terminology, but just to be sure let me explain what I understand to be coupled DE's (or CDEs); A set of DEs with the all derivatives taken with respect to a single parameter t and each DE depending on the functions f1,f2,...,fn. If you guys would like to correct me on nomenclature, I'd be glad to hear it.

Now that definitions are out of the way, I can begin to ask my questions. You don't have to answer all of them, though that would be great as well =).

1)Where can I find some good resources on methods to solve CDEs (websites, books, etc..)

2)How can I solve this system:

ax''+bx+cy=d
ex''+fy''=g

Where a,b,c,d,e,f,g are constants and x and y is what were looking for. A general solution is ideal, but if that is impossible here is some initial conditions.

x(0)=0; x'(0)=0
y(0)=0; y'(0)=0

From what I understand, this could possibly be solved with Laplace Transform, however my math is a little lacking in that department so while your reading this question, I may be brushing up on the subject.

A technique I've seen used is to integrate / differentiate the equations until some substitution is possible.

So..

ax''+bx+cy=d
ex''+fy''=g
=>
ax'''+bx''+cy''=0
ex''+fy''=g
=>
ax''' + bx'' + (c/f)(g-ex'') = 0
=>
ax''' + bx'' - (ce/f)x'' = -(cg/f)
=>
ax''' + (b - ce/f)x'' = -(cg/f)
=>
w' + (b/a - ce/af)w = -(cg/af)
=>
w' + Mw = N

Which can easily be solved, yielding x''. From that, you should be able to get the form of x' and x. Then... well, y'', y', and y should be solvable as well. Applying initial conditions should handle the four arbitrary constants introduced by x''->x', x'->x, y''->y', y'->y, but I'm not sure I remember off-hand how to handle the constant introduced by x'''->x''. There must be a way, though.

Hi!

Since the equations a linear, you could try following:

Any ODE of order 2 can be rewritten as a system of 2 first-order ODEs, e.g.:

x=x(t), v=v(t)

x''+x'+x=0

v=x'
v'+v+x=0

x'=v
v'=-v-x

$$\frac{d}{dt}\left(\begin{array}{c}x\\v\end{array}\right)=\left(\begin{array}{cc}0&1\\-1&-1\end{array}\right)\left(\begin{array}{c}x\\v\end{array}\right)$$

In your case each equation will produce another 2, so you'll end up with a system of 4 coupled linear first-oder ODEs.(one usually says of such system to have the order 4)

Then you separate in the LHSs the derivatives, and everything else in the RHSs. You have to then once again rewrite the system in terms of matrices and vectors, to be able to perform a basis transformation on the matrix.

This transformation is usually a DIAGONALISATION. However, some matrices are not diagonalisable where you have to transform them to their Jordan normal form.

After all this algebraic stuff you have achieved the following very important and useful thing:
Your equations have been (fully, in case the matrix is diagonalisable) decoupled and are independably solvable :)

hope you can follow it :)

best regards,
marin

All right thanks guys, you've all given me great insights on how to solve these problems in the future. And if anyone wants to take a shot at it, how would one solve a coupled partial differential equation (I've taken a course in PDE's so don't worry bout that part). Thanks guys.

[tex]x^2\sqrt{x}[\tex]


text:
# Is XOR adequate for encrypting truly random data? [duplicate]

It is well-known that the two-time pad is very insecure. However, it seems unexploitable in the case where the plaintext is indistinguishable from random (ex. symmetric keys).

Is this property useful?

Note: I don't plan on using this in production.

• easiest way to mitigate is compressing the input before x-or. – kelalaka Jan 27 '16 at 10:58
• @kelalaka: if the input plaintext is indistinguishable from random, compression doesn't work. In fact, many compression algorithms would detect that the compression algorithm is actually expanding the text, and drop back to a 'output the plaintext as-is' mode – poncho Jan 27 '16 at 14:49
• On a side note, you could ask; why would you want to send a uniformly random symmetric key using OTP (or two time pad)? If you are already sharing a uniformly random key for OTP, then in many cases you can probably use this shared randomness to do whatever it is you need to do. – Guut Boy Jan 27 '16 at 14:56

By two-time pad I assume you mean using a one time pad key to encrypt two messages. Lets say $K$ is the key and $m_1, m_2$ are your messages. Then from the ciphertexts $c_1 = m_1 \oplus K$ and $c_2 = m_2 \oplus K$ an adversary could trivially learn information such as $x = c_1 \oplus c_2 = m_1 \oplus m_2$. Whether or not this information is "exploitable" may be application specific (in general it is very hard to say what "exploitable" should mean). However, the fact is that you are leaking information on your secret messages and you should be very careful.
Take the following example of how this could go very wrong: Say I want to send two random 128 bit strings $m_1$ and $m_2$ to a friend who should then use $x = m_1 \oplus m_2$ as an AES key. If I send $m_1$ and $m_2$ using regular OTP then there is no problem. Using the two-time pad, as described above, the AES key is revealed.
• The other standard objection to two-time pad is that if the attacker somehow learns $m_1$, he then gets $m_2$ for free. – poncho Jan 27 '16 at 14:44


text:
# Anharmonicity in Hybrid and Inorganic Perovskite Materials used for Photovoltaics Applications References

* Corresponding author
2 LICSEN - Laboratoire Innovation en Chimie des Surfaces et NanoSciences
NIMBE UMR 3685 - Nanosciences et Innovation pour les Matériaux, la Biomédecine et l'Energie (ex SIS2M)
Abstract : Hybrid organic-inorganic perovskite materials have emerged over the past five years as absorber layers for new high-efficiency yet low-cost solar cells that combine the advantages of organic and inorganic semiconductors. Despite this sky rocketing evolution, the physics behind the electronic transport in these materials is still poorly understood. Here, employing the linear response (DFPT) approach of Density Functional Theory (DFT) and frozen phonon calculations, we reveal strong anharmonic effects in the inorganic CsPbI$_3$ perovskite structure compared to the hybrid CH$_3$ NH$_3$ PbI$_3$ (MAPbI$_3$) material, and found a double-well instability at the center of the Brillouin Zone. We show that previously reported soft modes are stabilized at the actual lower symmetry equilibrium structure, which occurs in a very flat energy landscape. These findings highlight the crucial role played by temperature in these materials, showing that this perovskite structure can oscillate between two equilibrium states at room temperature. Taking into account these low energy-highly occupied phonon states into the models used for electron-phonon interactions and band gap calculations could lead to a better understanding of the electrical transport properties of perovskite solar cells.
Document type :
Conference papers
Domain :

Cited literature [3 references]

https://hal-cea.archives-ouvertes.fr/cea-02340988
Contributor : Serge Palacin Connect in order to contact the contributor
Submitted on : Thursday, October 31, 2019 - 10:28:24 AM
Last modification on : Thursday, July 1, 2021 - 4:44:36 PM
Long-term archiving on: : Saturday, February 1, 2020 - 3:32:22 PM

### File

Marronnier_JPH2017.pdf
Files produced by the author(s)

### Identifiers

• HAL Id : cea-02340988, version 1

### Citation

Arthur Marronnier, Heejae Lee, Chloé Dindault, Denis Tondelier, Bernard Geffroy, et al.. Anharmonicity in Hybrid and Inorganic Perovskite Materials used for Photovoltaics Applications References. Journées Perovskites Hybrides, May 2017, Angers, France. ⟨cea-02340988⟩

Record views


text:
# mailbox — Manipulate mailboxes in various formats¶

Source code: Lib/mailbox.py

This module defines two classes, Mailbox and Message, for accessing and manipulating on-disk mailboxes and the messages they contain. Mailbox offers a dictionary-like mapping from keys to messages. Message extends the email.message module’s Message class with format-specific state and behavior. Supported mailbox formats are Maildir, mbox, MH, Babyl, and MMDF.

Module email
Represent and manipulate messages.

## Mailbox objects¶

class mailbox.Mailbox

A mailbox, which may be inspected and modified.

The Mailbox class defines an interface and is not intended to be instantiated. Instead, format-specific subclasses should inherit from Mailbox and your code should instantiate a particular subclass.

The Mailbox interface is dictionary-like, with small keys corresponding to messages. Keys are issued by the Mailbox instance with which they will be used and are only meaningful to that Mailbox instance. A key continues to identify a message even if the corresponding message is modified, such as by replacing it with another message.

Messages may be added to a Mailbox instance using the set-like method add() and removed using a del statement or the set-like methods remove() and discard().

Mailbox interface semantics differ from dictionary semantics in some noteworthy ways. Each time a message is requested, a new representation (typically a Message instance) is generated based upon the current state of the mailbox. Similarly, when a message is added to a Mailbox instance, the provided message representation’s contents are copied. In neither case is a reference to the message representation kept by the Mailbox instance.

The default Mailbox iterator iterates over message representations, not keys as the default dictionary iterator does. Moreover, modification of a mailbox during iteration is safe and well-defined. Messages added to the mailbox after an iterator is created will not be seen by the iterator. Messages removed from the mailbox before the iterator yields them will be silently skipped, though using a key from an iterator may result in a KeyError exception if the corresponding message is subsequently removed.

Warning

Be very cautious when modifying mailboxes that might be simultaneously changed by some other process. The safest mailbox format to use for such tasks is Maildir; try to avoid using single-file formats such as mbox for concurrent writing. If you’re modifying a mailbox, you must lock it by calling the lock() and unlock() methods before reading any messages in the file or making any changes by adding or deleting a message. Failing to lock the mailbox runs the risk of losing messages or corrupting the entire mailbox.

Mailbox instances have the following methods:

add(message)

Add message to the mailbox and return the key that has been assigned to it.

Parameter message may be a Message instance, an email.message.Message instance, a string, a byte string, or a file-like object (which should be open in binary mode). If message is an instance of the appropriate format-specific Message subclass (e.g., if it’s an mboxMessage instance and this is an mbox instance), its format-specific information is used. Otherwise, reasonable defaults for format-specific information are used.

Changed in version 3.2: Support for binary input was added.

remove(key)
__delitem__(key)
discard(key)

Delete the message corresponding to key from the mailbox.

If no such message exists, a KeyError exception is raised if the method was called as remove() or __delitem__() but no exception is raised if the method was called as discard(). The behavior of discard() may be preferred if the underlying mailbox format supports concurrent modification by other processes.

__setitem__(key, message)

Replace the message corresponding to key with message. Raise a KeyError exception if no message already corresponds to key.

As with add(), parameter message may be a Message instance, an email.message.Message instance, a string, a byte string, or a file-like object (which should be open in binary mode). If message is an instance of the appropriate format-specific Message subclass (e.g., if it’s an mboxMessage instance and this is an mbox instance), its format-specific information is used. Otherwise, the format-specific information of the message that currently corresponds to key is left unchanged.

iterkeys()
keys()

Return an iterator over all keys if called as iterkeys() or return a list of keys if called as keys().

itervalues()
__iter__()
values()

Return an iterator over representations of all messages if called as itervalues() or __iter__() or return a list of such representations if called as values(). The messages are represented as instances of the appropriate format-specific Message subclass unless a custom message factory was specified when the Mailbox instance was initialized.

Note

The behavior of __iter__() is unlike that of dictionaries, which iterate over keys.

iteritems()
items()

Return an iterator over (key, message) pairs, where key is a key and message is a message representation, if called as iteritems() or return a list of such pairs if called as items(). The messages are represented as instances of the appropriate format-specific Message subclass unless a custom message factory was specified when the Mailbox instance was initialized.

get(key, default=None)
__getitem__(key)

Return a representation of the message corresponding to key. If no such message exists, default is returned if the method was called as get() and a KeyError exception is raised if the method was called as __getitem__(). The message is represented as an instance of the appropriate format-specific Message subclass unless a custom message factory was specified when the Mailbox instance was initialized.

get_message(key)

Return a representation of the message corresponding to key as an instance of the appropriate format-specific Message subclass, or raise a KeyError exception if no such message exists.

get_bytes(key)

Return a byte representation of the message corresponding to key, or raise a KeyError exception if no such message exists.

New in version 3.2.

get_string(key)

Return a string representation of the message corresponding to key, or raise a KeyError exception if no such message exists. The message is processed through email.message.Message to convert it to a 7bit clean representation.

get_file(key)

Return a file-like representation of the message corresponding to key, or raise a KeyError exception if no such message exists. The file-like object behaves as if open in binary mode. This file should be closed once it is no longer needed.

Changed in version 3.2: The file object really is a binary file; previously it was incorrectly returned in text mode. Also, the file-like object now supports the context management protocol: you can use a with statement to automatically close it.

Note

Unlike other representations of messages, file-like representations are not necessarily independent of the Mailbox instance that created them or of the underlying mailbox. More specific documentation is provided by each subclass.

__contains__(key)

Return True if key corresponds to a message, False otherwise.

__len__()

Return a count of messages in the mailbox.

clear()

Delete all messages from the mailbox.

pop(key, default=None)

Return a representation of the message corresponding to key and delete the message. If no such message exists, return default. The message is represented as an instance of the appropriate format-specific Message subclass unless a custom message factory was specified when the Mailbox instance was initialized.

popitem()

Return an arbitrary (key, message) pair, where key is a key and message is a message representation, and delete the corresponding message. If the mailbox is empty, raise a KeyError exception. The message is represented as an instance of the appropriate format-specific Message subclass unless a custom message factory was specified when the Mailbox instance was initialized.

update(arg)

Parameter arg should be a key-to-message mapping or an iterable of (key, message) pairs. Updates the mailbox so that, for each given key and message, the message corresponding to key is set to message as if by using __setitem__(). As with __setitem__(), each key must already correspond to a message in the mailbox or else a KeyError exception will be raised, so in general it is incorrect for arg to be a Mailbox instance.

Note

Unlike with dictionaries, keyword arguments are not supported.

flush()

Write any pending changes to the filesystem. For some Mailbox subclasses, changes are always written immediately and flush() does nothing, but you should still make a habit of calling this method.

lock()

Acquire an exclusive advisory lock on the mailbox so that other processes know not to modify it. An ExternalClashError is raised if the lock is not available. The particular locking mechanisms used depend upon the mailbox format. You should always lock the mailbox before making any modifications to its contents.

unlock()

Release the lock on the mailbox, if any.

close()

Flush the mailbox, unlock it if necessary, and close any open files. For some Mailbox subclasses, this method does nothing.

### Maildir¶

class mailbox.Maildir(dirname, factory=None, create=True)

A subclass of Mailbox for mailboxes in Maildir format. Parameter factory is a callable object that accepts a file-like message representation (which behaves as if opened in binary mode) and returns a custom representation. If factory is None, MaildirMessage is used as the default message representation. If create is True, the mailbox is created if it does not exist.

It is for historical reasons that dirname is named as such rather than path.

Maildir is a directory-based mailbox format invented for the qmail mail transfer agent and now widely supported by other programs. Messages in a Maildir mailbox are stored in separate files within a common directory structure. This design allows Maildir mailboxes to be accessed and modified by multiple unrelated programs without data corruption, so file locking is unnecessary.

Maildir mailboxes contain three subdirectories, namely: tmp, new, and cur. Messages are created momentarily in the tmp subdirectory and then moved to the new subdirectory to finalize delivery. A mail user agent may subsequently move the message to the cur subdirectory and store information about the state of the message in a special “info” section appended to its file name.

Folders of the style introduced by the Courier mail transfer agent are also supported. Any subdirectory of the main mailbox is considered a folder if '.' is the first character in its name. Folder names are represented by Maildir without the leading '.'. Each folder is itself a Maildir mailbox but should not contain other folders. Instead, a logical nesting is indicated using '.' to delimit levels, e.g., “Archived.2005.07”.

Note

The Maildir specification requires the use of a colon (':') in certain message file names. However, some operating systems do not permit this character in file names, If you wish to use a Maildir-like format on such an operating system, you should specify another character to use instead. The exclamation point ('!') is a popular choice. For example:

import mailbox
mailbox.Maildir.colon = '!'

The colon attribute may also be set on a per-instance basis.

Maildir instances have all of the methods of Mailbox in addition to the following:

list_folders()

Return a list of the names of all folders.

get_folder(folder)

Return a Maildir instance representing the folder whose name is folder. A NoSuchMailboxError exception is raised if the folder does not exist.

add_folder(folder)

Create a folder whose name is folder and return a Maildir instance representing it.

remove_folder(folder)

Delete the folder whose name is folder. If the folder contains any messages, a NotEmptyError exception will be raised and the folder will not be deleted.

clean()

Delete temporary files from the mailbox that have not been accessed in the last 36 hours. The Maildir specification says that mail-reading programs should do this occasionally.

Some Mailbox methods implemented by Maildir deserve special remarks:

add(message)
__setitem__(key, message)
update(arg)

Warning

These methods generate unique file names based upon the current process ID. When using multiple threads, undetected name clashes may occur and cause corruption of the mailbox unless threads are coordinated to avoid using these methods to manipulate the same mailbox simultaneously.

flush()

All changes to Maildir mailboxes are immediately applied, so this method does nothing.

lock()
unlock()

Maildir mailboxes do not support (or require) locking, so these methods do nothing.

close()

Maildir instances do not keep any open files and the underlying mailboxes do not support locking, so this method does nothing.

get_file(key)

Depending upon the host platform, it may not be possible to modify or remove the underlying message while the returned file remains open.

maildir man page from qmail
The original specification of the format.
Using maildir format
Notes on Maildir by its inventor. Includes an updated name-creation scheme and details on “info” semantics.
maildir man page from Courier
Another specification of the format. Describes a common extension for supporting folders.

### mbox¶

class mailbox.mbox(path, factory=None, create=True)

A subclass of Mailbox for mailboxes in mbox format. Parameter factory is a callable object that accepts a file-like message representation (which behaves as if opened in binary mode) and returns a custom representation. If factory is None, mboxMessage is used as the default message representation. If create is True, the mailbox is created if it does not exist.

The mbox format is the classic format for storing mail on Unix systems. All messages in an mbox mailbox are stored in a single file with the beginning of each message indicated by a line whose first five characters are “From “.

Several variations of the mbox format exist to address perceived shortcomings in the original. In the interest of compatibility, mbox implements the original format, which is sometimes referred to as mboxo. This means that the Content-Length header, if present, is ignored and that any occurrences of “From ” at the beginning of a line in a message body are transformed to “>From ” when storing the message, although occurrences of “>From ” are not transformed to “From ” when reading the message.

Some Mailbox methods implemented by mbox deserve special remarks:

get_file(key)

Using the file after calling flush() or close() on the mbox instance may yield unpredictable results or raise an exception.

lock()
unlock()

Three locking mechanisms are used—dot locking and, if available, the flock() and lockf() system calls.

mbox man page from qmail
A specification of the format and its variations.
mbox man page from tin
Another specification of the format, with details on locking.
Configuring Netscape Mail on Unix: Why The Content-Length Format is Bad
An argument for using the original mbox format rather than a variation.
“mbox” is a family of several mutually incompatible mailbox formats
A history of mbox variations.

### MH¶

class mailbox.MH(path, factory=None, create=True)

A subclass of Mailbox for mailboxes in MH format. Parameter factory is a callable object that accepts a file-like message representation (which behaves as if opened in binary mode) and returns a custom representation. If factory is None, MHMessage is used as the default message representation. If create is True, the mailbox is created if it does not exist.

MH is a directory-based mailbox format invented for the MH Message Handling System, a mail user agent. Each message in an MH mailbox resides in its own file. An MH mailbox may contain other MH mailboxes (called folders) in addition to messages. Folders may be nested indefinitely. MH mailboxes also support sequences, which are named lists used to logically group messages without moving them to sub-folders. Sequences are defined in a file called .mh_sequences in each folder.

The MH class manipulates MH mailboxes, but it does not attempt to emulate all of mh’s behaviors. In particular, it does not modify and is not affected by the context or .mh_profile files that are used by mh to store its state and configuration.

MH instances have all of the methods of Mailbox in addition to the following:

list_folders()

Return a list of the names of all folders.

get_folder(folder)

Return an MH instance representing the folder whose name is folder. A NoSuchMailboxError exception is raised if the folder does not exist.

add_folder(folder)

Create a folder whose name is folder and return an MH instance representing it.

remove_folder(folder)

Delete the folder whose name is folder. If the folder contains any messages, a NotEmptyError exception will be raised and the folder will not be deleted.

get_sequences()

Return a dictionary of sequence names mapped to key lists. If there are no sequences, the empty dictionary is returned.

set_sequences(sequences)

Re-define the sequences that exist in the mailbox based upon sequences, a dictionary of names mapped to key lists, like returned by get_sequences().

pack()

Rename messages in the mailbox as necessary to eliminate gaps in numbering. Entries in the sequences list are updated correspondingly.

Note

Already-issued keys are invalidated by this operation and should not be subsequently used.

Some Mailbox methods implemented by MH deserve special remarks:

remove(key)
__delitem__(key)
discard(key)

These methods immediately delete the message. The MH convention of marking a message for deletion by prepending a comma to its name is not used.

lock()
unlock()

Three locking mechanisms are used—dot locking and, if available, the flock() and lockf() system calls. For MH mailboxes, locking the mailbox means locking the .mh_sequences file and, only for the duration of any operations that affect them, locking individual message files.

get_file(key)

Depending upon the host platform, it may not be possible to remove the underlying message while the returned file remains open.

flush()

All changes to MH mailboxes are immediately applied, so this method does nothing.

close()

MH instances do not keep any open files, so this method is equivalent to unlock().

nmh - Message Handling System
MH & nmh: Email for Users & Programmers
A GPL-licensed book on mh and nmh, with some information on the mailbox format.

### Babyl¶

class mailbox.Babyl(path, factory=None, create=True)

A subclass of Mailbox for mailboxes in Babyl format. Parameter factory is a callable object that accepts a file-like message representation (which behaves as if opened in binary mode) and returns a custom representation. If factory is None, BabylMessage is used as the default message representation. If create is True, the mailbox is created if it does not exist.

Babyl is a single-file mailbox format used by the Rmail mail user agent included with Emacs. The beginning of a message is indicated by a line containing the two characters Control-Underscore ('\037') and Control-L ('\014'). The end of a message is indicated by the start of the next message or, in the case of the last message, a line containing a Control-Underscore ('\037') character.

Messages in a Babyl mailbox have two sets of headers, original headers and so-called visible headers. Visible headers are typically a subset of the original headers that have been reformatted or abridged to be more attractive. Each message in a Babyl mailbox also has an accompanying list of labels, or short strings that record extra information about the message, and a list of all user-defined labels found in the mailbox is kept in the Babyl options section.

Babyl instances have all of the methods of Mailbox in addition to the following:

get_labels()

Return a list of the names of all user-defined labels used in the mailbox.

Note

The actual messages are inspected to determine which labels exist in the mailbox rather than consulting the list of labels in the Babyl options section, but the Babyl section is updated whenever the mailbox is modified.

Some Mailbox methods implemented by Babyl deserve special remarks:

get_file(key)

In Babyl mailboxes, the headers of a message are not stored contiguously with the body of the message. To generate a file-like representation, the headers and body are copied together into an io.BytesIO instance, which has an API identical to that of a file. As a result, the file-like object is truly independent of the underlying mailbox but does not save memory compared to a string representation.

lock()
unlock()

Three locking mechanisms are used—dot locking and, if available, the flock() and lockf() system calls.

Format of Version 5 Babyl Files
A specification of the Babyl format.
The Rmail manual, with some information on Babyl semantics.

### MMDF¶

class mailbox.MMDF(path, factory=None, create=True)

A subclass of Mailbox for mailboxes in MMDF format. Parameter factory is a callable object that accepts a file-like message representation (which behaves as if opened in binary mode) and returns a custom representation. If factory is None, MMDFMessage is used as the default message representation. If create is True, the mailbox is created if it does not exist.

MMDF is a single-file mailbox format invented for the Multichannel Memorandum Distribution Facility, a mail transfer agent. Each message is in the same form as an mbox message but is bracketed before and after by lines containing four Control-A ('\001') characters. As with the mbox format, the beginning of each message is indicated by a line whose first five characters are “From “, but additional occurrences of “From ” are not transformed to “>From ” when storing messages because the extra message separator lines prevent mistaking such occurrences for the starts of subsequent messages.

Some Mailbox methods implemented by MMDF deserve special remarks:

get_file(key)

Using the file after calling flush() or close() on the MMDF instance may yield unpredictable results or raise an exception.

lock()
unlock()

Three locking mechanisms are used—dot locking and, if available, the flock() and lockf() system calls.

mmdf man page from tin
A specification of MMDF format from the documentation of tin, a newsreader.
MMDF
A Wikipedia article describing the Multichannel Memorandum Distribution Facility.

## Message objects¶

class mailbox.Message(message=None)

A subclass of the email.message module’s Message. Subclasses of mailbox.Message add mailbox-format-specific state and behavior.

If message is omitted, the new instance is created in a default, empty state. If message is an email.message.Message instance, its contents are copied; furthermore, any format-specific information is converted insofar as possible if message is a Message instance. If message is a string, a byte string, or a file, it should contain an RFC 2822-compliant message, which is read and parsed. Files should be open in binary mode, but text mode files are accepted for backward compatibility.

The format-specific state and behaviors offered by subclasses vary, but in general it is only the properties that are not specific to a particular mailbox that are supported (although presumably the properties are specific to a particular mailbox format). For example, file offsets for single-file mailbox formats and file names for directory-based mailbox formats are not retained, because they are only applicable to the original mailbox. But state such as whether a message has been read by the user or marked as important is retained, because it applies to the message itself.

There is no requirement that Message instances be used to represent messages retrieved using Mailbox instances. In some situations, the time and memory required to generate Message representations might not be acceptable. For such situations, Mailbox instances also offer string and file-like representations, and a custom message factory may be specified when a Mailbox instance is initialized.

### MaildirMessage¶

class mailbox.MaildirMessage(message=None)

A message with Maildir-specific behaviors. Parameter message has the same meaning as with the Message constructor.

Typically, a mail user agent application moves all of the messages in the new subdirectory to the cur subdirectory after the first time the user opens and closes the mailbox, recording that the messages are old whether or not they’ve actually been read. Each message in cur has an “info” section added to its file name to store information about its state. (Some mail readers may also add an “info” section to messages in new.) The “info” section may take one of two forms: it may contain “2,” followed by a list of standardized flags (e.g., “2,FR”) or it may contain “1,” followed by so-called experimental information. Standard flags for Maildir messages are as follows:

Flag Meaning Explanation
D Draft Under composition
F Flagged Marked as important
P Passed Forwarded, resent, or bounced
R Replied Replied to
T Trashed Marked for subsequent deletion

MaildirMessage instances offer the following methods:

get_subdir()

Return either “new” (if the message should be stored in the new subdirectory) or “cur” (if the message should be stored in the cur subdirectory).

Note

A message is typically moved from new to cur after its mailbox has been accessed, whether or not the message is has been read. A message msg has been read if "S" in msg.get_flags() is True.

set_subdir(subdir)

Set the subdirectory the message should be stored in. Parameter subdir must be either “new” or “cur”.

get_flags()

Return a string specifying the flags that are currently set. If the message complies with the standard Maildir format, the result is the concatenation in alphabetical order of zero or one occurrence of each of 'D', 'F', 'P', 'R', 'S', and 'T'. The empty string is returned if no flags are set or if “info” contains experimental semantics.

set_flags(flags)

Set the flags specified by flags and unset all others.

add_flag(flag)

Set the flag(s) specified by flag without changing other flags. To add more than one flag at a time, flag may be a string of more than one character. The current “info” is overwritten whether or not it contains experimental information rather than flags.

remove_flag(flag)

Unset the flag(s) specified by flag without changing other flags. To remove more than one flag at a time, flag maybe a string of more than one character. If “info” contains experimental information rather than flags, the current “info” is not modified.

get_date()

Return the delivery date of the message as a floating-point number representing seconds since the epoch.

set_date(date)

Set the delivery date of the message to date, a floating-point number representing seconds since the epoch.

get_info()

Return a string containing the “info” for a message. This is useful for accessing and modifying “info” that is experimental (i.e., not a list of flags).

set_info(info)

Set “info” to info, which should be a string.

When a MaildirMessage instance is created based upon an mboxMessage or MMDFMessage instance, the Status and X-Status headers are omitted and the following conversions take place:

Resulting state mboxMessage or MMDFMessage state
“cur” subdirectory O flag
F flag F flag
R flag A flag
S flag R flag
T flag D flag

When a MaildirMessage instance is created based upon an MHMessage instance, the following conversions take place:

Resulting state MHMessage state
“cur” subdirectory “unseen” sequence
“cur” subdirectory and S flag no “unseen” sequence
F flag “flagged” sequence
R flag “replied” sequence

When a MaildirMessage instance is created based upon a BabylMessage instance, the following conversions take place:

Resulting state BabylMessage state
“cur” subdirectory “unseen” label
“cur” subdirectory and S flag no “unseen” label
P flag “forwarded” or “resent” label
T flag “deleted” label

### mboxMessage¶

class mailbox.mboxMessage(message=None)

A message with mbox-specific behaviors. Parameter message has the same meaning as with the Message constructor.

Messages in an mbox mailbox are stored together in a single file. The sender’s envelope address and the time of delivery are typically stored in a line beginning with “From ” that is used to indicate the start of a message, though there is considerable variation in the exact format of this data among mbox implementations. Flags that indicate the state of the message, such as whether it has been read or marked as important, are typically stored in Status and X-Status headers.

Conventional flags for mbox messages are as follows:

Flag Meaning Explanation
O Old Previously detected by MUA
D Deleted Marked for subsequent deletion
F Flagged Marked as important

The “R” and “O” flags are stored in the Status header, and the “D”, “F”, and “A” flags are stored in the X-Status header. The flags and headers typically appear in the order mentioned.

mboxMessage instances offer the following methods:

get_from()

Return a string representing the “From ” line that marks the start of the message in an mbox mailbox. The leading “From ” and the trailing newline are excluded.

set_from(from_, time_=None)

Set the “From ” line to from_, which should be specified without a leading “From ” or trailing newline. For convenience, time_ may be specified and will be formatted appropriately and appended to from_. If time_ is specified, it should be a time.struct_time instance, a tuple suitable for passing to time.strftime(), or True (to use time.gmtime()).

get_flags()

Return a string specifying the flags that are currently set. If the message complies with the conventional format, the result is the concatenation in the following order of zero or one occurrence of each of 'R', 'O', 'D', 'F', and 'A'.

set_flags(flags)

Set the flags specified by flags and unset all others. Parameter flags should be the concatenation in any order of zero or more occurrences of each of 'R', 'O', 'D', 'F', and 'A'.

add_flag(flag)

Set the flag(s) specified by flag without changing other flags. To add more than one flag at a time, flag may be a string of more than one character.

remove_flag(flag)

Unset the flag(s) specified by flag without changing other flags. To remove more than one flag at a time, flag maybe a string of more than one character.

When an mboxMessage instance is created based upon a MaildirMessage instance, a “From ” line is generated based upon the MaildirMessage instance’s delivery date, and the following conversions take place:

Resulting state MaildirMessage state
R flag S flag
O flag “cur” subdirectory
D flag T flag
F flag F flag
A flag R flag

When an mboxMessage instance is created based upon an MHMessage instance, the following conversions take place:

Resulting state MHMessage state
R flag and O flag no “unseen” sequence
O flag “unseen” sequence
F flag “flagged” sequence
A flag “replied” sequence

When an mboxMessage instance is created based upon a BabylMessage instance, the following conversions take place:

Resulting state BabylMessage state
R flag and O flag no “unseen” label
O flag “unseen” label
D flag “deleted” label

When a Message instance is created based upon an MMDFMessage instance, the “From ” line is copied and all flags directly correspond:

Resulting state MMDFMessage state
R flag R flag
O flag O flag
D flag D flag
F flag F flag
A flag A flag

### MHMessage¶

class mailbox.MHMessage(message=None)

A message with MH-specific behaviors. Parameter message has the same meaning as with the Message constructor.

MH messages do not support marks or flags in the traditional sense, but they do support sequences, which are logical groupings of arbitrary messages. Some mail reading programs (although not the standard mh and nmh) use sequences in much the same way flags are used with other formats, as follows:

Sequence Explanation
unseen Not read, but previously detected by MUA
replied Replied to
flagged Marked as important

MHMessage instances offer the following methods:

get_sequences()

Return a list of the names of sequences that include this message.

set_sequences(sequences)

Set the list of sequences that include this message.

add_sequence(sequence)

Add sequence to the list of sequences that include this message.

remove_sequence(sequence)

Remove sequence from the list of sequences that include this message.

When an MHMessage instance is created based upon a MaildirMessage instance, the following conversions take place:

Resulting state MaildirMessage state
“unseen” sequence no S flag
“replied” sequence R flag
“flagged” sequence F flag

When an MHMessage instance is created based upon an mboxMessage or MMDFMessage instance, the Status and X-Status headers are omitted and the following conversions take place:

Resulting state mboxMessage or MMDFMessage state
“unseen” sequence no R flag
“replied” sequence A flag
“flagged” sequence F flag

When an MHMessage instance is created based upon a BabylMessage instance, the following conversions take place:

Resulting state BabylMessage state
“unseen” sequence “unseen” label

### BabylMessage¶

class mailbox.BabylMessage(message=None)

A message with Babyl-specific behaviors. Parameter message has the same meaning as with the Message constructor.

Certain message labels, called attributes, are defined by convention to have special meanings. The attributes are as follows:

Label Explanation
unseen Not read, but previously detected by MUA
deleted Marked for subsequent deletion
filed Copied to another file or mailbox
forwarded Forwarded
edited Modified by the user
resent Resent

By default, Rmail displays only visible headers. The BabylMessage class, though, uses the original headers because they are more complete. Visible headers may be accessed explicitly if desired.

BabylMessage instances offer the following methods:

get_labels()

Return a list of labels on the message.

set_labels(labels)

Set the list of labels on the message to labels.

add_label(label)

Add label to the list of labels on the message.

remove_label(label)

Remove label from the list of labels on the message.

get_visible()

Return an Message instance whose headers are the message’s visible headers and whose body is empty.

set_visible(visible)

Set the message’s visible headers to be the same as the headers in message. Parameter visible should be a Message instance, an email.message.Message instance, a string, or a file-like object (which should be open in text mode).

update_visible()

When a BabylMessage instance’s original headers are modified, the visible headers are not automatically modified to correspond. This method updates the visible headers as follows: each visible header with a corresponding original header is set to the value of the original header, each visible header without a corresponding original header is removed, and any of Date, From, Reply-To, To, CC, and Subject that are present in the original headers but not the visible headers are added to the visible headers.

When a BabylMessage instance is created based upon a MaildirMessage instance, the following conversions take place:

Resulting state MaildirMessage state
“unseen” label no S flag
“deleted” label T flag
“forwarded” label P flag

When a BabylMessage instance is created based upon an mboxMessage or MMDFMessage instance, the Status and X-Status headers are omitted and the following conversions take place:

Resulting state mboxMessage or MMDFMessage state
“unseen” label no R flag
“deleted” label D flag

When a BabylMessage instance is created based upon an MHMessage instance, the following conversions take place:

Resulting state MHMessage state
“unseen” label “unseen” sequence

### MMDFMessage¶

class mailbox.MMDFMessage(message=None)

A message with MMDF-specific behaviors. Parameter message has the same meaning as with the Message constructor.

As with message in an mbox mailbox, MMDF messages are stored with the sender’s address and the delivery date in an initial line beginning with “From “. Likewise, flags that indicate the state of the message are typically stored in Status and X-Status headers.

Conventional flags for MMDF messages are identical to those of mbox message and are as follows:

Flag Meaning Explanation
O Old Previously detected by MUA
D Deleted Marked for subsequent deletion
F Flagged Marked as important

The “R” and “O” flags are stored in the Status header, and the “D”, “F”, and “A” flags are stored in the X-Status header. The flags and headers typically appear in the order mentioned.

MMDFMessage instances offer the following methods, which are identical to those offered by mboxMessage:

get_from()

Return a string representing the “From ” line that marks the start of the message in an mbox mailbox. The leading “From ” and the trailing newline are excluded.

set_from(from_, time_=None)

Set the “From ” line to from_, which should be specified without a leading “From ” or trailing newline. For convenience, time_ may be specified and will be formatted appropriately and appended to from_. If time_ is specified, it should be a time.struct_time instance, a tuple suitable for passing to time.strftime(), or True (to use time.gmtime()).

get_flags()

Return a string specifying the flags that are currently set. If the message complies with the conventional format, the result is the concatenation in the following order of zero or one occurrence of each of 'R', 'O', 'D', 'F', and 'A'.

set_flags(flags)

Set the flags specified by flags and unset all others. Parameter flags should be the concatenation in any order of zero or more occurrences of each of 'R', 'O', 'D', 'F', and 'A'.

add_flag(flag)

Set the flag(s) specified by flag without changing other flags. To add more than one flag at a time, flag may be a string of more than one character.

remove_flag(flag)

Unset the flag(s) specified by flag without changing other flags. To remove more than one flag at a time, flag maybe a string of more than one character.

When an MMDFMessage instance is created based upon a MaildirMessage instance, a “From ” line is generated based upon the MaildirMessage instance’s delivery date, and the following conversions take place:

Resulting state MaildirMessage state
R flag S flag
O flag “cur” subdirectory
D flag T flag
F flag F flag
A flag R flag

When an MMDFMessage instance is created based upon an MHMessage instance, the following conversions take place:

Resulting state MHMessage state
R flag and O flag no “unseen” sequence
O flag “unseen” sequence
F flag “flagged” sequence
A flag “replied” sequence

When an MMDFMessage instance is created based upon a BabylMessage instance, the following conversions take place:

Resulting state BabylMessage state
R flag and O flag no “unseen” label
O flag “unseen” label
D flag “deleted” label

When an MMDFMessage instance is created based upon an mboxMessage instance, the “From ” line is copied and all flags directly correspond:

Resulting state mboxMessage state
R flag R flag
O flag O flag
D flag D flag
F flag F flag
A flag A flag

## Exceptions¶

The following exception classes are defined in the mailbox module:

exception mailbox.Error

The based class for all other module-specific exceptions.

exception mailbox.NoSuchMailboxError

Raised when a mailbox is expected but is not found, such as when instantiating a Mailbox subclass with a path that does not exist (and with the create parameter set to False), or when opening a folder that does not exist.

exception mailbox.NotEmptyError

Raised when a mailbox is not empty but is expected to be, such as when deleting a folder that contains messages.

exception mailbox.ExternalClashError

Raised when some mailbox-related condition beyond the control of the program causes it to be unable to proceed, such as when failing to acquire a lock that another program already holds a lock, or when a uniquely-generated file name already exists.

exception mailbox.FormatError

Raised when the data in a file cannot be parsed, such as when an MH instance attempts to read a corrupted .mh_sequences file.

## Examples¶

A simple example of printing the subjects of all messages in a mailbox that seem interesting:

import mailbox
for message in mailbox.mbox('~/mbox'):
subject = message['subject']       # Could possibly be None.
if subject and 'python' in subject.lower():
print(subject)

To copy all mail from a Babyl mailbox to an MH mailbox, converting all of the format-specific information that can be converted:

import mailbox
destination = mailbox.MH('~/Mail')
destination.lock()
for message in mailbox.Babyl('~/RMAIL'):
destination.flush()
destination.unlock()

This example sorts mail from several mailing lists into different mailboxes, being careful to avoid mail corruption due to concurrent modification by other programs, mail loss due to interruption of the program, or premature termination due to malformed messages in the mailbox:

import mailbox
import email.errors

list_names = ('python-list', 'python-dev', 'python-bugs')

boxes = {name: mailbox.mbox('~/email/%s' % name) for name in list_names}
inbox = mailbox.Maildir('~/Maildir', factory=None)

for key in inbox.iterkeys():
try:
message = inbox[key]
except email.errors.MessageParseError:
continue                # The message is malformed. Just leave it.

for name in list_names:
list_id = message['list-id']
if list_id and name in list_id:
# Get mailbox to use
box = boxes[name]

# Write copy to disk before removing original.
# If there's a crash, you might duplicate a message, but
# that's better than losing a message completely.
box.lock()