Found my first C project



  • This was the final project at the end of a semester (in my first year of college) where we spent the first couple months learning Matlab, and the last few learning C. Before this course, I had never written a program.

    #define _CRT_SECURE_NO_DEPRECATE
    #define FILE_LOCATION "/home/buddyandorn/Desktop/input.txt"
    #include <stdio.h>
    #include <time.h>
    #include <string.h>
    #ifndef MAXVAL_USHORT
    	#define MAXVAL_USHORT 0xFFFF
    #endif
    
    // You can assume no inputs will exceed these values:
    #define MAX_BOXES 100
    #define MAX_PARCELS 100
    
    typedef union {
    	unsigned long long longIndex[1];
    	unsigned int intIndex[2];
    	unsigned short shortIndex[4];
    	unsigned char charIndex[8];
    } mask;
    
    //Globals (every level of function needs access to these):
    	static int bestWeight, capacity, numBoxes_total, numItems_total, itemList[MAX_PARCELS] = {0}, lookupTable[4][MAXVAL_USHORT + 1] = {0};
    	static unsigned long long current[MAX_BOXES + 1] = {0}, best[MAX_BOXES + 1] = {0};
    
    
    
    static __inline int HighestSetBit(unsigned long long index);
    static __inline int BitCount(long long index);
    
    
    
    static int Pack(
    	int numItems,
    	int weight,
    	int boxNum,
    	long long accumulator
    );
    /*This function, given an array of items listed by weight will pack the items into as few boxes as possible, or if not all items can fit in a box, will pack the boxes in such a way that the least weight is left un-packed. It does this by recursion, with each successive call being passed the total weight of items left unpacked and the number of the box to be packed. The level of recursion is limited by the global variable 'bestNum', which is updated if all items are packed into a fewer number of boxes
    
    The array itemList is referenced by a logical index, of up to MAX_ITEMS number of bits, where for each set bit an element of the array is packed into the current box (so an index value of 2^n + 2^m means that itemList[m] and itemList[n] are packed).
    This means that every possible subset of the array can be tested by counting thru every value of the index variable*/
    
    
    
    
    
    
    int main(int argc, char *argv[])
    {
    	time_t timeEnd, timeStart;
    	FILE *fp;
    	int keepTime = 0, asciiAdjust = 0, dataSet, i, j;
    	
    
    	for (i = 0; i < argc; i++) {
    		if ( strcmp( argv[i], "/t" ) == 0 ) {
    			keepTime = 1;
    		}
    	}
    
    
    
    //Get user input:
    	fp = fopen(FILE_LOCATION, "r");
    	if (fp == NULL) {
    		printf("Error opening file %s\n", FILE_LOCATION);
    		return 1;
    	}
    
    
    	printf("Perfect Parcel Packing\nEngGen 131 Semester 2 2009\nWhich data set? ");
    	if (!scanf("%d",&dataSet)) {
    		printf("\nNo input detected\n");
    		return 1;
    	}
    	if (dataSet < 1) {
    		printf("\nInput not valid\n");
    		return 1;
    	}
    //Find the selected data set:
    	for (i = 0; i < dataSet; i++) {
    		do {
    			j = fgetc(fp);
    			if (j == EOF) {
    				printf("\nData set %d not found in file\n", dataSet);
    				return 1;
    			}
    		} while (j != '#');
    	}
    //Read and display values from file:
    	if (!(fscanf(fp, "%d", &numBoxes_total) && fscanf(fp, "%d", &capacity) && fscanf(fp, "%d", &numItems_total) )) {
    		printf("\nError reading from file (check the format)\n");
    		return 1;
    	} else if (numBoxes_total > MAX_BOXES) {
    		printf("\nError reading from file (too many boxes)\n");
    		return 1;
    	} else if (numItems_total > MAX_PARCELS) {
    		printf("\nError reading from file (too many parcels)\n");
    		return 1;
    	}
    	printf("\nNumber of boxes: %d\nBox capacity: %d\nNumber of items: %d\nItem weights: ", numBoxes_total, capacity, numItems_total);
    	for (i = 0; i < numItems_total; i++) {
    		if (!fscanf(fp, "%d", &itemList[i])) {
    			printf("\nError reading list of items from file\n");
    			return 1;
    		}			
    		printf("%d ", itemList[i]);				//Items are stored in a single array, and referenced by an array of logical indices
    		if (itemList[i] <= capacity) {				//Initially the best weight of un-packed items == the total weight of items
    			bestWeight += itemList[i];			//Items that do not fit into a box are not included in that
    		} else {						//total, but are considered 'packed', in box 0
    
    //Use i number of bit shifts to move the set bit to the ith position
    			current[0] += (unsigned long long)1 << i;
    		}
    	}
    
    
    	if (fclose(fp) == EOF) {
    		printf("\nError closing file %s", FILE_LOCATION);
    	}
    	
    	for ( i = MAXVAL_USHORT; i; i--) {
    		for (j = 0; j < (int)sizeof(short) * 8; j++) {
    			if (i & 1 << j) {
    				lookupTable[0][i] += itemList[j];
    				lookupTable[1][i] += itemList[j + 16];
    				lookupTable[2][i] += itemList[j + 32];
    				lookupTable[3][i] += itemList[j + 48];
    			}
    		}
    	}
    		
    		
    
    
    
    	time(&timeStart);
    	Pack(numItems_total, bestWeight, 1, current[0]);
    	time(&timeEnd);
    
    
    
    
    
    //Output results:
    
    	for (i = 1; i <= numBoxes_total; i++) {
    		if (i == 27) {
    			asciiAdjust = 6;				//lower case letters start 6 places after upper case Z
    		}
    		printf("\n%c: ", '@' + i + asciiAdjust);		//'@' is the last ASCII character before the letter 'A'
    		for (j = 0; j < numItems_total; j++) {
    			if (best[i] & (unsigned long long)1 << j ) {		//bit shifts again, this time using them to test one bit at a time
    				printf("%d ", itemList[j]);
    			}
    		}
    	}
    
    	printf("\nUnassigned:");	
    	for (j = 0; j < numItems_total; j++) {
    		if (best[0] & (unsigned long long)(1 << j) ) {
    			printf(" %d", itemList[j]);
    		}
    	}
    	printf("\n");
    
    	if (keepTime) {									//Show total running time for the Pack() function.
    		keepTime = (int)difftime(timeEnd, timeStart);
    		if (keepTime / 3600)
    			printf("%d hours, ", keepTime/3600);
    		if ((keepTime%=3600)/60)
    			printf("%d minutes, ", keepTime/60);
    		printf("%d seconds elapsed\n", keepTime%60);
    	}
    printf("bestWeight %d\n", bestWeight);
    	return 0;
    }
    
    
    
    
    
    
    static int Pack(
    	int numItems, 
    	int weight, 
    	int boxNum, 
    	long long accumulator
    )
    {
    
    	unsigned long long index, temp;
    	mask tempIndex;
    	int weightPacked;
    	unsigned int i, j;
    
    
    	//If all remaining items can be packed into the current box, update best values and return 1, to indicate success
    	if (weight <= capacity) {
    		best[boxNum] = ~accumulator;
    		bestWeight = 0;
    		for (i = boxNum; i <= (unsigned)numBoxes_total; ) {
    			i++;
    			best[i] = 0;
    		}
    		for (i = boxNum; i > 0;) {
    			 i--;
    			best[i] = current[i];
    		}
    		return 1;
    	}
    
    	index = 0;
    
    	for (i = numItems; i > 0;) {
    		i--;
    		if (~accumulator & (unsigned long long)1ull << i) {
    			if ( itemList[i] > bestWeight ) {
    				index += (unsigned long long)1ull << i;
    				break;
    			}
    		}
    	}
    //printf("\nbox %d  index %u, weight %d %d", boxNum, index.intIndex[0], itemList[i], bestWeight);
    
    
    	if (!index) {
    		index = 1;
    	}
    
    
    
    
    	while (index < ((unsigned long long)1 << numItems)) {	
    //printf("\nbox %d  index %u, weight %d", boxNum, index.intIndex[0], weight);
    
    		if (index & accumulator) {
    			index += (index & accumulator);
    			continue;
    		}
    
    		tempIndex.longIndex[0] = index;
    
    		weightPacked = 0;
    		
    		weightPacked += lookupTable[0][ tempIndex.shortIndex[0] ];
    		weightPacked += lookupTable[1][ tempIndex.shortIndex[1] ];
    		weightPacked += lookupTable[2][ tempIndex.shortIndex[2] ];
    		weightPacked += lookupTable[3][ tempIndex.shortIndex[3] ];
    
    
    		
    		
    		if (weightPacked > capacity) {
    			
    
    			while (weightPacked > capacity) {
    
    				temp = tempIndex.longIndex[0] & ~(tempIndex.longIndex[0] - 1);
    				tempIndex.longIndex[0] &= tempIndex.longIndex[0] - 1;
    
    				weightPacked = 0;
    		
    				weightPacked += lookupTable[0][ tempIndex.shortIndex[0] ];
    				weightPacked += lookupTable[1][ tempIndex.shortIndex[1] ];
    				weightPacked += lookupTable[2][ tempIndex.shortIndex[2] ];
    				weightPacked += lookupTable[3][ tempIndex.shortIndex[3] ];
    			}
    			index += temp;
    			continue;
    		}
    
    
    
    
    
    		
    		current[boxNum] = index;
    
    
    		if (boxNum == numBoxes_total) {	
    			//If this is is the best solution yet, store current array as best array.
    			if ((weight - weightPacked) < bestWeight) {
    				bestWeight = (weight - weightPacked);
    				best[0] = current[0] | ~(accumulator | index);
    				for (i = numBoxes_total; i;) {
    				best[i] = current[i];
    				 i--;			
    				}
    			}
    			index++;					
    			continue;
    
    		} else if(HighestSetBit(index)) {
    			Pack(HighestSetBit(index), weight - weightPacked, boxNum + 1, accumulator | index);
    		}	
    
    		index++;
    
    	}		
    
    	return 0;
    }
    
    #ifdef _WIN64
    static __inline int HighestSetBit(unsigned long long index)
    {
    	unsigned long long highBit;
    	_BitScanReverse64( &highBit, index);
    	return (int)highBit;
    }
    #else
    	#ifdef _WIN32
    static __inline int HighestSetBit(unsigned long long index)
    {
    	unsigned int highBit;
    	mask tempIndex;
    
    	tempIndex.longIndex[0] = index;
    
    	if (!(_BitScanReverse( &highBit, tempIndex.intIndex[0]))) {
    		_BitScanReverse( &highBit, tempIndex.intIndex[1]);		//note this function uses the opposite meanings of 
    		highBit += 32;
    	}
    	return highBit;
    }
    	#else
    static __inline int HighestSetBit(unsigned long long index)
    {
    	unsigned long long highBit;
    
    	 __asm(
    		"bsrq %1, %0" 
    		:"=r" (highBit) 
    		:"r" (index)
    	);
    	return (int)highBit;
    }
    	#endif
    #endif
    
    static __inline int BitCount(long long index)
    {
    	index = (index & 0x1111111111111111) + ((index >> 1) & 0x1111111111111111);
    	index = (index & 0x0f0f0f0f0f0f0f0f) + ((index >> 2) & 0x0f0f0f0f0f0f0f0f);
    	index = (index & 0x00ff00ff00ff00ff) + ((index >> 4) & 0x00ff00ff00ff00ff);
    	index = (index & 0x0000ffff0000ffff) + ((index >> 8) & 0x0000ffff0000ffff);
    	index = (index & 0x00000000ffffffff) + ((index >> 16)& 0x00000000ffffffff);
    
    	return index;
    }
    	
    

  • Winner of the 2016 Presidential Election

    Was part of the assignment to use every C feature you could think of?



  • No, I'm just insufferable.



  • @Buddy said:

    No, I'm just insufferable.

    QFT


  • :belt_onion:

    Just a few observations, some perhaps just my own nitpicking so I would like to know what others think:

    1. You need more comments, mainly for function input, output, ...
      Comments in the same line with // are too far
    2. Function names in C usually are lower case
    3. It is more common to use underline than camlecase notation
    4. Using inline unless strictly necessary should be left to the compiler, if used to make the code faster it has to be tested to make sure it really is effective.
    5. Using static for function is only to hide the symbol from other units. Is there some provable speed advantage? Was that the intention?


  • You need more comments, mainly for function input, output, ...Comments in the same line with // are too far

    Absolutely. I was thinkning some of the variable names could have been better, too.

    Function names in C usually are lower case
    It is more common to use underline than camlecase notation

    Yeah, I'm not sure what I was thinking there. Maybe we'd learnt camelcase when we were taught matlab and I thought it would be a good idea to keep the same style across languages.

    Using inline unless strictly necessary should be left to the compiler, if used to make the code faster it has to be tested to make sure it really is effective.

    It's not that I didn't try to profile my code, it's just that I didn't succeed. Trwtf is the professor, imo, for giving us a project with strict execution time requirements without teaching us how to find hot spots. But for HighestSetBit, the whole point was that that function was supposed to compile to a single assembly instruction, so it made sense to me at the time that it should be inline. Actually checking that the compiler produced that, though, was another thing I failed at.

    Using static for function is only to hide the symbol from other units. Is there some provable speed advantage? Was that the intention?

    I honestly don't know. I didn't even know what compilation units were at that time—hence everything being in one big file (that's also the reason for the terrible vertical spacing: I was doing a lot of scrolling up & down and it made it easier to see where I was).


  • :belt_onion:

    Actually the code is not that bad. I have seen far far worse. It has a consistency within itself that makes sense.
    @Buddy said:

    taught matlab

    That is TR :wtf:. It is a disservice to teach students MATLAB when Python can do it better and is a real general language.



  • Needs more ??(trigraphs??)(https://msdn.microsoft.com/en-us/library/bt0y4awe.aspx) ??=seventiesProblems



  • Looks to me as if it's just as well BitCount() doesn't get called anywhere, because it doesn't work: 0x0c has two bits set, but your function will return zero for it.


  • Discourse touched me in a no-no place

    @dse said:

    Function names in C usually are lower case

    System library functions are that. Stuff with mixed case is free for user code.



  • @dse said:

    It is a disservice to teach students MATLAB when Python can do it better and is a real general language.

    Bullshit. It's never a disservice to teach students multiple languages.

    In this case, although MATLAB is not a very good general purpose language, it's a very good language for teaching basic programming practice, carrying out real calculations, but without getting bogged down in minutiæ. Not to mention that, for the tasks it's designed for, MATLAB kicks python down the stairs and then does unspeakable things to its dying corpse.

    And, when this code was written, it would have been Python 2.x. Which had far less mathematical tools available for it.



  • @tufty said:

    In this case, although MATLAB is not a very good general purpose language, it's a very good language for teaching basic programming practice, carrying out real calculations, but without getting bogged down in minutiæ.
    I can't agree with this enough. I sometimes wonder if this scares off potential developers. You need to start people off on something where you can see results of what you've done very quickly and give someone a feeling of accompolishment at the same time. Its very hard to keep people interested when they're spending most of their time wrestleing with the compiler and the only output is text in the console. It's why I think scratch used in primary and secondary school is a brillant idea.



  • @DogsB said:

    I sometimes wonder if this scares off potential developers. You need to start people off on something where you can see results of what you've done very quickly and give someone a feeling of accompolishment at the same time. Its very hard to keep people interested when they're spending most of their time wrestleing with the compiler and the only output is text in the console.

    It certainly kept me away from programming for a few years. The amount of shit and obstacles you have to understand before you can start writing and running proper functions is staggering.

    Even Python, which is probably the easiest "real" programming language, ships with an official "GUI", IDLE, that would already have been shitty in 1995 and doesn't respect any UI conventions. Installing that as a noob will just result in hating everything related to computers for a year. It's like they're trying to keep people away.



  • @Buddy said:

    ```
    static __inline int BitCount(long long index)
    {
    index = (index & 0x1111111111111111) + ((index >> 1) & 0x1111111111111111);
    index = (index & 0x0f0f0f0f0f0f0f0f) + ((index >> 2) & 0x0f0f0f0f0f0f0f0f);
    index = (index & 0x00ff00ff00ff00ff) + ((index >> 4) & 0x00ff00ff00ff00ff);
    index = (index & 0x0000ffff0000ffff) + ((index >> 8) & 0x0000ffff0000ffff);
    index = (index & 0x00000000ffffffff) + ((index >> 16)& 0x00000000ffffffff);

    return index;
    

    }

    
    Seems to me that what you were aiming for should be closer to
    
    ```c
    static __inline int BitCount(unsigned long long i)
    {
        /* i can be thought of as 64 individual set-bit counts. */
        i = (i & 0x5555555555555555) + (i >> 1 & 0x5555555555555555);
        /* i now holds 32 2-bit counts, one for each original 2-bit field. */
        i = (i & 0x3333333333333333) + (i >> 2 & 0x3333333333333333);
        /* i now holds 16 4-bit counts, one for every original 4-bit field. Max
        value of each count is 4, so the MSB in every 4-bit field is guaranteed 0.
        This allows remaining consolidations to be done without pre-masking, as
        carry between fields cannot happen. */
        i = i + (i >> 4) & 0x0f0f0f0f0f0f0f0f;
        /* i now holds 8 8-bit counts, one for every original 8-bit field. There
        are now enough padding 0s to allow the next three consolidations to be
        done without any masking at all, as garbage fields cannot overflow. */
        i += i >> 8;
        i += i >> 16;
        i += i >> 32;
        /* Everything outside the least significant byte is garbage. */
        return i & 127;
    }
    

    The first move, from 64 1-bit fields to 32 2-bit fields, can be simplified:

    static __inline int BitCount(unsigned long long i)
    {
        /* Process bits in pairs, converting 00 -> 00, 01 -> 01, 10 -> 01, 11 -> 10.
        Do this by subtracting the MSB of each pair from the whole pair; that never
        causes a carry outside the pair, so a normal full-width subtract can safely
        process all 32 pairs in one go. */
        i -= i >> 1 & 0x5555555555555555;
        /* i now holds 32 2-bit counts, one for each original 2-bit field. */
        i = (i & 0x3333333333333333) + (i >> 2 & 0x3333333333333333);
        /* i now holds 16 4-bit counts, one for every original 4-bit field. Max
        value of each count is 4, so the MSB in every 4-bit field is guaranteed 0.
        This allows remaining consolidations to be done without pre-masking, as
        carry between fields cannot happen. */
        i = i + (i >> 4) & 0x0f0f0f0f0f0f0f0f;
        /* i now holds 8 8-bit counts, one for each original 8-bit field. There
        are now enough padding 0s to allow the next three consolidations to be
        done without any masking at all, as garbage fields cannot overflow. */
        i += i >> 8;
        i += i >> 16;
        i += i >> 32;
        /* Everything outside the least significant byte is garbage. */
        return i & 127;
    }
    

    Using a multiply can squash the last few steps:

    static __inline int BitCount(unsigned long long i)
    {
        /* Process bits in pairs, converting 00 -> 00, 01 -> 01, 10 -> 01, 11 -> 10.
        Do this by subtracting the MSB of each pair from the whole pair; that never
        causes a carry outside the pair, so a normal full-width subtract can safely
        process all 32 pairs in one go. */
        i -= i >> 1 & 0x5555555555555555;
        /* i now holds 32 2-bit counts, one for each original 2-bit field. */
        i = (i & 0x3333333333333333) + (i >> 2 & 0x3333333333333333);
        /* i now holds 16 4-bit counts, one for every original 4-bit field. Max
        value of each count is 4, so the MSB in every 4-bit field is guaranteed 0.
        This allows remaining consolidations (firstly to 8 8-bit counts, then to
        a final 64-bit count) to be done without masking, as carry between fields
        cannot happen. */
        return (i + (i >> 4) & 0x0f0f0f0f0f0f0f0f) * 0x0101010101010101 >> 56;
    }
    

    More here.



  • Or just use __builtin_popcount (unsigned int x) in GCC. Similar functions are likely to exist on other compilers.


  • Discourse touched me in a no-no place

    @tufty said:

    Bullshit. It's never a disservice to teach students multiple languages.

    Even if the languages are Brainfuck, APL, and Piet? :trolleybus:



  • Even if it's lobjan.

    Well, maybe not. Gotta draw that line somewhere.

    Brainfuck and Piet are, although jokey, interesting in many ways (although not as much fun as INTERCAL); APL is a serious programming language. Nothing particularly wrong with learning any of them.



  • @Buddy said:

    Yeah, I'm not sure what I was thinking there. Maybe we'd learnt camelcase when we were taught matlab and I thought it would be a good idea to keep the same style across languages.

    The standard C style on Mac Classic was title case for a lot of stuff.

    The Mac Toolbox (standard library stuffs) was all ported from Pascal, so. It worked a little weird in C. Notably you had to deal with Pascal strings a lot. (The first byte is the length.)



  • @dse said:

    That is TR :wtf:. It is a disservice to teach students MATLAB when Python can do it better and is a real general language.

    Python can't even draw a simple graph without yanking in like 26 dependencies.



  • @DogsB said:

    I can't agree with this enough. I sometimes wonder if this scares off potential developers. You need to start people off on something where you can see results of what you've done very quickly and give someone a feeling of accompolishment at the same time. Its very hard to keep people interested when they're spending most of their time wrestleing with the compiler and the only output is text in the console. It's why I think scratch used in primary and secondary school is a brillant idea.

    When I was a kid, we had Rocky's Boots and HyperCard.

    Now kids have: "fuck you kids, open source took over, there's nothing but VIM!"



  • @blakeyrat said:

    you had to deal with Pascal strings

    What, and deprive oneself of stack smashing bug opportunities?

    NO! NEVER SURRENDER! YOU SHALL USE ONLY ONE FLAG AND THAT IS THE UNION FLAG!



  • @PleegWat said:

    Or just use __builtin_popcount (unsigned int x) in GCC.

    Depending how much speed you need, those may or may not do better than the approach above. You'd think they would, but popcounts are not as widely used as e.g. memset() so the compiler vendor might not have done as good a job as possible.

    As ever, do the simplest thing first and optimize where the profiler says you need to.


  • Discourse touched me in a no-no place

    @anonymous234 said:

    It certainly kept me away from programming for a few years. The amount of shit and obstacles you have to understand before you can start writing and running proper functions is staggering.

    There's a few possible routes into programming. I like starting people out with a simple read-eval-print-loop, since that's very immediate: tell the computer to do something, and it does it right away and tells you what happened. After they've got used to that, teach functions (or procedures or subroutines or … whatever the language calls them) which is just take the stuff you were typing and putting it in a named container that you can call again and again. Once you've got that, you can make the step to keeping the code in a file and then you're bootstrapped up to the next level of complexity. :smile:


  • :belt_onion:

    @blakeyrat said:

    Python can't even draw a simple graph without yanking in like 26 dependencies.

    You just need MatplotLib, even the documents are same as MATLAB. Plus, you are not installing dependencies all the time. If you are installing on multipel machines, keep them in a requirements.txt file and you have them with pip install -r requirements.txt.

    @tufty said:

    Bullshit. It's never a disservice to teach students multiple languages.

    So why not teaching them FoxPro or QBasic? I really enjoyed them, but they are dead. Bullshit is assuming that their time is worthless because they are just students. Teach them multiple languages, but certainly select some that could make them few bucks sooner than later, and something that is free.

    @tufty said:

    MATLAB is not a very good general purpose language, it's a very good language for teaching basic programming practice

    Bullshit, you have never seen any MATLAB script more than one page. It is passing gigantic god object cell-arrays around that all happily add more properties to. It is a POS from 80s with a horrible editor they want to sell as IDE that does not have any proper project management, like a fucking simple tree of resources or code files.

    @tufty said:

    Not to mention that, for the tasks it's designed for, MATLAB kicks python down the stairs and then does unspeakable things to its dying corpse.

    Like exactly what?

    @tufty said:

    And, when this code was written, it would have been Python 2.x. Which had far less mathematical tools available for it.

    Correct. Python was not anywhere close to beating MATLAB say 6-7 years ago. You just have o use SciPy, NumPy, Pandas, ... to believe with your own eyes how much progress has been made in scientific Python while MathWorks was spending dollars to feed schools with free licenses to hook the professors.



  • Language advocacy mush?

    Python is a piece of shit. There. I've said it. It's a horrible fucking piece of shit that uses whitespace to express structure. It tries to be Lisp but can't even manage to be better than BASIC. Stick it in a git repo and erase the history with great prejudice.

    Filed under: Am I doing this right?



  • @dse said:

    pip install -r requirements.txt

    Right; beginners LOVE command lines. They also love you to yell out "fuck your MOM!" 57 times while teaching them. You should totally use both techniques.


  • :belt_onion:

    I hate spaces as scope in Python, that and many other language warts. But still compared to MATLAB it is much much better. Write a better scripting language that I can use in an iPython-like environment and has all those libraries and I would gladly switch.

    @blakeyrat said:

    Right; beginners LOVE command lines. They also love you to yell out "fuck your MOM!" 57 times while teaching them. You should totally use both techniques.

    They can install Sage, or Anaconda.



  • @dse said:

    They can install Sage

    The air traffic control system? I thought it only ran on old mainframes.


  • Discourse touched me in a no-no place

    @dse said:

    Write a better scripting language that I can use in an iPython-like environment and has all those libraries and I would gladly switch.

    Well, according to jupyter (which is what iPython is evolving into), there's more than 40 languages it works with.

    I don't like Python. It's not the whitespace thing. It just doesn't work the way I think.



  • @blakeyrat said:

    They also love you to yell out "fuck your MOM!" 57 times while teaching them.

    Ah, good times!

    10 PRINT "FUCK YOUR MOM!"
    20 GOTO 10
    

    Loops were more advanced, of course.


  • Grade A Premium Asshole

    @blakeyrat said:

    Mac Classic

    @blakeyrat said:

    HyperCard

    When I read the first post, I thought to myself, "If blakey is in here, he will mention Mac Classic or HyperCard." He did both.



  • @boomzilla said:

    Loops were more advanced, of course.

    10 A$ = "FUCK YOUR MOM!"
    20 A = (39 - LEN(A$)) / 2
    30 PRINT TAB(SIN(X) * A + A + 1); A$
    40 X = X + 0.3
    50 GOTO 30
    

  • :belt_onion:

    X is undefined in the first loop, this has no mother fucking output.



  • This is old-school BASIC, so undefined numeric variables are auto-created with an initial value of 0.



  • My first C project is now long gone and lost in some HDD. It was for the PalmPilot and was done in some IDE I can't remember now. Fun times.



  • Come to think of it, this was the first year of a BEng where every student took all the same courses before we picked our specialization. For those that didn't pick softeng or computer systems , and especially for the ones who went into engsci, which aiui was mostly modeling and operations research, matlab and c were probably the only languages they might ever need.

    Also I seem to recall some kind of matlab-integrated system that they used in the control systems labs for configuring pid contollers and the like that I highly doubt anything in python could match, even now.


  • sockdevs

    Depends on the dialect of BASIC. ZX Basic for example would throw a fatal error at you for that.

    2 Variable not found, 30: 2



  • @Eldelshell said:

    My first C project is now long gone and lost in some HDD.

    I'm pretty sure I know where mine is. It's part of my uni senior project. Unfortunately, it's on a 5.25" floppy that I no longer have any means to read — if the bits haven't rotted away to nothing over the last almost 30 years.



  • @HardwareGeek said:

    Unfortunately, it's on a 5.25" floppy that I no longer have any means to read

    I think I finally threw those out a few years ago... But I still have enough old code to go "what the hell was I thinking!"



  • @Buddy said:

    Also I seem to recall some kind of matlab-integrated system that they used in the control systems labs for configuring pid contollers and the like that I highly doubt anything in python could match, even now.

    Simulink aka Poor Man's Labview aka Spaghetti Code Illustrated aka The Death of 1000 Lines...



  • At least command lines are precise. I can email a beginner a command to run and they can just copy/paste it.

    With GUIs it's like "click this thing, then this other thing shows up, don't click that, click this other thing. Wait. There's no Properties button? What do you see on the screen? Read me everything you see on the screen. No, start reading from the top. No. Higher up. No -- up under the title bar. No! Not the title bar itself! Fuck your MOM! Fuck your MOM! ...etc."



  • But they won't. They'll make typos and blame you. Or for the next several years you'll be diagnosing environments only to find out the idiot in question has been typing ps -ef | grep user | cut -f2 | xargs kill -9 again. If I find out who taught him that one...



  • @blakeyrat said:

    @dse said:
    That is TR :wtf:. It is a disservice to teach students MATLAB when Python can do it better and is a real general language.

    Python can't even draw a simple graph without yanking in like 26 dependencies.

    What do you think is MATLAB doing over the, I don't know, 3 minutes it takes to start? Or in the ~4 GB it occupies?

    @dse said:

    @tufty said:
    Not to mention that, for the tasks it's designed for, MATLAB kicks python down the stairs and then does unspeakable things to its dying corpse.

    Like exactly what?

    Having official toolboxes for every single engineering subsubsubfield that contain every single domain specific function you could ever need.

    @smallshellscript said:

    Simulink aka Poor Man's Labview

    Like LabView wasn't poor enough.


  • Discourse touched me in a no-no place

    @superjer said:

    With GUIs it's like "click this thing, then this other thing shows up, don't click that, click this other thing. Wait. There's no Properties button? What do you see on the screen? Read me everything you see on the screen. No, start reading from the top. No. Higher up. No -- up under the title bar. No! Not the title bar itself! Fuck your MOM! Fuck your MOM! ...etc."

    Or they allow you to remote in, but won't leave well alone while you're trying to figure out WTF is going on. Particularly doing things like closing the window containing the debugging information that you're trying to read and understand “because I always just close such windows immediately”.



  • @marczellm said:

    What do you think is MATLAB doing over the, I don't know, 3 minutes it takes to start? Or in the ~4 GB it occupies?

    Who cares? Point is it fucking works, and its users don't have to even learn the word "dependencies".



  • On the other hand, they have to learn about toolboxes, and pay a lot for them.


  • Discourse touched me in a no-no place

    @marczellm said:

    On the other hand, they have to learn about toolboxes, and pay a lot for them.

    All of which comes under the heading of “Give us all your moneys, then we fuck you!”

    Close to the perfection of @Lorne_Kates but not quite there…



  • Well that's why I always send them something like this

    echo ☃✄ツ && pip install whatever
    

    so they won't even try to type it in.


  • Discourse touched me in a no-no place

    @PleegWat said:

    . If I find out who taught him that one

    Bah, just edit his .bashrc or something and alias ps to echo "CUT THAT SHIT OUT"; logout.


  • :belt_onion:

    @marczellm said:

    Having official toolboxes for every single engineering subsubsubfield that contain every single domain specific function you could ever need.

    Canned responses and black boxes are only good for well defined academics and professors. If you want to develop an algorithm, you will end up implementing your own secret sauce and those toolboxes worth shit, only you end up paying many grands for an 80s-era scripting language.


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.