Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

2010 Homework No. 3 - findsuss

Name: Anonymous 2010-01-15 22:56

Write a program in the language of your choice that takes a string and inputs "SUSSMAN" for every time those characters appear. In case I'm not being clear, that means output "SUSSMAN" for every 3 's's and 1 'u', 'm', 'a', and 'n' in the string. Inputting "ssssumanssssssssssuman", for example, would print "SUSSMAN" twice. "ssuman", however, would print nothing.

I've written an inelegant solution in C, which I'll post in a second. It tends to crash after execution, however, and I cannot for the life of me figure out what I'm doing wrong. It does everything it's supposed to but refuses to terminate politely. Even stranger, it only happens when there is enough characters for two or more sussmen. I guess the problem is in the susscount loop, but I can't figure out where. Mind giving me a hand, /prog/?

Name: Anonymous 2010-01-15 22:58

/*       SUSSMAN        */
/* BEWARE, SHITTY COEDS */

#include <stdio.h>

int main()
{
    char suss[1];
    char letters[] = "SUMANsuman";
    int count[5] = {0}; /* S, U, M, A, N */
    int susscount = 0;
   
    int x, c;
   
    printf("Enter a string (terminate with 'Q'): ");
    for (x = 0; scanf("%c", &suss[x]), suss[x] != 'Q'; x++);
   
    for (x = 0; suss[x] != 'Q'; x++)
    {
        for (c = 0; c <= 9; c++)
        {
            if (suss[x] == letters[c])
            {
                if (c < 5)
                    count[c]++;
                else
                    count[c-5]++;
            }
        }
    }
   
    while (count[0] > 0)
    {
   
        for (x = 1, c = 0; x < 5; x++)
        {
            if (count[x] >= 1)
                c++;
            count[x]--;
        }
       
        if (count[0] >= 3)
            c++;
        count[0] -= 3;
       
        if (c == 5)
            susscount++;
    }
   
    for (; susscount > 0; susscount--)
        printf("SUSSMAN\n");
   
    return 0;
}

Name: Anonymous 2010-01-15 23:04

char suss[1];

Surely that can’t be right. Also, I am a fan of the following notation:

    while (susscount --> 0)
        printf("SUSSMAN\n");

Name: Anonymous 2010-01-15 23:13

>>3

GCC bitches if you use char suss[];

Also, COOL FREE UNDOCUMENTED PERL OPERATOR

Name: Anonymous 2010-01-15 23:13

The homework series was less bad back when it was not done by the guy appending numbers to it.

Name: Anonymous 2010-01-15 23:20

>>5

;_;

Name: Anonymous 2010-01-15 23:34

>>4
Please stop trying to use C.

Name: Anonymous 2010-01-15 23:38

●█████▄▄▄▄▄▄▄▄
▄▅███████▅▄▃▂
███sage tank███████►
◥☼▲⊙▲⊙▲⊙▲⊙▲⊙▲☼◤

Name: HMA FAN 2010-01-16 0:10

Your C code is a fucking abomination.

Here is some better SATORI CODE with COOL FREE ANNOTATIONS.
import Array
import Data.Maybe
import Data.Char

countChars :: String -> [(Char, Int)]
countChars = assocs . accumArray (+) 0 (minBound,maxBound)
             . (map (\x -> (toUpper x,1)))

countSuss :: [(Char,Int)] -> Int
countSuss m = minimum $ [floor . (/3) . fromIntegral $ count 'S'] ++ map count "UMAN"
    where count c = fromMaybe 0 $ lookup c m

findSuss = unwords . flip take (repeat "SUSSMAN") . countSuss . countChars


Example:
*Main> findSuss "SSS SSS SSS U U U M M M A A A N N N N N N N"
"SUSSMAN SUSSMAN SUSSMAN"

Name: Anonymous 2010-01-16 0:23

Golfing version to further ridicule your implementation.
import Array
import Data.Maybe
import Data.Char

findSuss xs = unwords $ take sussmen (repeat "SUSSMAN")
    where counts = assocs . accumArray (+) 0 (minBound,maxBound) . (map (\x -> (toUpper x,1))) $ xs
          sussmen = minimum $ [floor . (/3) . fromIntegral $ count 'S'] ++ map count "UMAN"
          count c = fromMaybe 0 $ lookup c counts

Name: Anonymous 2010-01-16 0:25


;;; I first misunderstood this problem as a search for 3 consecutive S, U, ...
;;; Here's the solution for that:

(defun sussman-count (string search-string
                        &aux (string (string-upcase string))
                           (search-string (string-upcase search-string)))
  (let ((s-len (length search-string))
        (b-len (length string)))
    (do ((index (search search-string string)
                (search search-string string :start2 index))
         (i 0 (1+ i)))
        ((not index) i)
      (when (<= (+ index s-len) b-len)
        (incf index s-len)))))

;;; (sussman-count "ssssumanssssssssssuman" "sss" ) => 4

(defun make-search-string (string count)
  (map 'list
       #'(lambda (char)
           (make-string count :initial-element char))
       (remove-duplicates (string-upcase string))))

(defparameter *search-strings* '#.(make-search-string "Sussman" 3))
;=> ("UUU" "SSS" "MMM" "AAA" "NNN")

(defun count-all-sussmans (string search-strings)
  (loop
    for search-string in search-strings
    sum (sussman-count string search-string)))

; (count-all-sussmans "ssssusmanssssssssssuuumannnn" *search-strings* ) => 6

(defun print-sussmans (n &optional (stream t))
  (loop repeat n do (format stream "~&Sussman~&")))

;CL-USER> (print-sussmans 2 )
;Sussman
;Sussman

(defun print-required-sussmans (string)
  (print-sussmans (count-all-sussmans string *search-strings*)))

;CL-USER> (print-required-sussmans "ssssusmanssssssssssuuumannnn")
;Sussman
;Sussman
;Sussman
;Sussman
;Sussman
;Sussman


;;; Okay, so this solves a harder problem than what OP wanted. It's my fault that I misunderstood the problem.

;;; So this counts every s,u,m,a,n character, and for every 3 of them prints as many sussmans as needed
(defun count-letters (string &optional (letters "Sussman"))
  (loop for letter across (remove-duplicates (string-upcase letters))
     sum (truncate (count letter string :key #'char-upcase :test #'char=) 3)))

(defun print-wizardly-sussmans (string)
  (loop repeat (count-letters string) do (format t "~&SUSSMAN~&")))

; (count-letters "Sssuuusssmaan" "su") => 3

;CL-USER> (print-wizardly-sussmans "ssssumanssssssssssuman")
;Sussman
;Sussman
;Sussman
;Sussman


;;; Oh fuck, I misread the problem again, " that means output "SUSSMAN" for every 3 's's and 1 'u', 'm', 'a', and 'n' in the string."
;;; Solution should be ( reusing the original sussman-count from up there )

(defun print-wizardly-sussmans-for-real (string)
  (loop repeat (sussman-count string "sssuman") do (format t "~&SUSSMAN~&")))

;CL-USER> (print-wizardly-sussmans-for-real "ssssumanssssssssssuman")
;SUSSMAN
;SUSSMAN

; That seems to be right. I hope I understood the problem correctly this last time.


I really shouldn't code while sleeping.

Name: Anonymous 2010-01-16 0:36

Just reposting your code more cleanly for comparison purposes.
(defun count-letters (string &optional (letters "Sussman"))
  (loop for letter across (remove-duplicates (string-upcase letters))
     sum (truncate (count letter string :key #'char-upcase :test #'char=) 3)))
(defun print-wizardly-sussmans-for-real (string)
  (loop repeat (sussman-count string "sssuman") do (format t "~&SUSSMAN~&")))

Name: Anonymous 2010-01-16 0:39

Damn where's the COBOL guy when you need him most?...

Name: Anonymous 2010-01-16 0:42

Actually should be


(defun sussman-count (string search-string
                        &aux (string (string-upcase string))
                           (search-string (string-upcase search-string)))
  (let ((s-len (length search-string))
        (b-len (length string)))
    (do ((index (search search-string string)
                (search search-string string :start2 index))
         (i 0 (1+ i)))
        ((not index) i)
      (when (<= (+ index s-len) b-len)
        (incf index s-len)))))
(defun print-wizardly-sussmans-for-real (string)
  (loop repeat (sussman-count string "sssuman") do (format t "~&SUSSMAN~&")))


but I believe your implementation is more complicated than needed, >>11-kun. "smanuss" should print a Sussman, whether the letters are in order or not. It does depend on how we interpret >>1.

Name: Anonymous 2010-01-16 0:45

>>8

I wasn't trying to write anything impressive. My goal here is to:
A) Illustrate a problem to be solved
and
B) Provide a (somewhat, in this case) working solution to the problem to prove that it can be solved

The quicker I can write a solution to the problem, the more time people have to write their own solutions, which is all that I really care about - seeing /prog/'s code. My implementation may have been ugly, but I was able to pump it out in 20 minutes, so I'm happy.

Name: Anonymous 2010-01-16 0:55

>>14
I didn't understand the exact meaning in >>1, so I wrote 3 solutions for possible meanings I thought were possible. Maybe one has the right meaning, maybe none. I'll read OP's statements more carefully tommorow and see if they match my understanding or not.
sussman-count is indeed more complicated than it should be, it's pretty low level. It can be written more elegantly for sure.

Name: Anonymous 2010-01-16 1:21

>>15
I wasn't trying to write anything impressive.
You certainly accomplished that.
Protip: C doesn't have variable length arrays or array bounds checking. Your scanf loop is writing all over random memory, and it's a miracle it doesn't crash right there (though it will if you input longer strings).

Name: Anonymous 2010-01-16 2:01

>>17

I'm a dipshit, you fixed it. I never realized that C didn't have variable length arrays. In fact, I've even thought on several occasions that "fixed length arrays would be much easier to work with, why would a supposedly low-level language allow this, etc," never managing to make the connection that the language was just letting me get away with it the whole time. Thank you for explaining what my mistake was, I would have kept doing it if you hadn't explained that.

I'm not an experienced C programmer, if you couldn't tell; I'm just picking this stuff up as I go along.

Name: Anonymous 2010-01-16 2:40

>>17
What is your definition of a variable length array? You can just malloc your array as you please. The array size is static, but you can extend(re-alloc) the array if needed. Some C functions are unsafe as they can write to a buffer without having a way to control how much they would write, or if they should re-allocate a new buffer. IMO, it's much simpler and safer if the callee allocates the buffer for you and maybe provides some length metadata on the side. It's possible to design safe APIs for C and use C safely, but the coder needs to make a conscious effort to do so. (Or the coder could just use something more high-level than C...)

Name: Anonymous 2010-01-16 3:38

>>17
Protip: C doesn't have variable length arrays
Yes, it does.

Name: clever guy 2010-01-16 3:58


s,u,m,a,n = 0,0,0,0,0
local line = io.read()
for i = 1, #line do
  local letter = line:sub(i, i)
  if _G[letter] then _G[letter] = _G[letter] + 1 end
end
for i = 1, math.min(s / 3, u, m, a, n) do print"Sussman" end

Obviously, using lua made it too easy. I might do one in C or something later.

Name: Anonymous 2010-01-16 4:07

>>18
YHBT. Good luck with C, it's a painful language to program in, especially at first, but necessary. Avoid scanf, it's unsafe and not needed here. Just use getchar and loop while( c != '\n' ).
>>16
Oh I know, I didn't correct anything in your code, I was just reposting it cleanly because the noise impeded my reading. It's a different interpretation of OP from >>9 but not wrong per se.
>>20
realloc my anus

Name: Anonymous 2010-01-16 4:48

>>20,22
C99 has them.  Unless they are a GCC extension.  I forget.

Name: Anonymous 2010-01-16 4:56

>>19,20
Maybe you should read the thread.

>>23
Both. C99 has them, and GNU C has an incompatible implementation.
Everyone knows C99 isn't C, though.

Name: Anonymous 2010-01-16 5:08

AMATEUR LEVEL SOLUTIONS

<?php 


function subchr_count($needle, $haystack) {
    $haycount = count_chars($haystack,1);
    $needlecount = count_chars($needle,1);
    $retval = 0;
   
    do {
        foreach ($needlecount as $chr => $num) {
            if (!isset($haycount[$chr]) ||
                ($haycount[$chr] -= $num) < 0) {
                break 2;
            }
           
        }
    } while (++$retval);
   
    return $retval;
}


function main()
{
    while(true) {
        $continue = 'y';
        fwrite(STDOUT, "\nEnter string of characters to search in: \n"); 
        do { 
            $haystack = fgets(STDIN); 
        } while (trim($haystack) == ''); 
       
        fwrite(STDOUT, "\nEnter string of characters to search for: \n"); 
        do { 
            $needle = rtrim(fgets(STDIN), "\r\n");
        } while ($needle == '');
       
        $t = microtime(true);
        $result = subchr_count($needle, $haystack);
        $t = microtime(true) - $t;
        $result ?
            $findings = "\nCongratulations, \"$needle\" was found $result times!" :
            $findings = "\nI'm sorry, \"$needle\" was not found.";
        fwrite(STDOUT, $findings);
        fwrite(STDOUT, "\nSearch query took " . number_format($t, 5) . " seconds.\n");
       
       
        fwrite(STDOUT, "\nTry again? y/n \n"); 
        while(true) {
            $continue = fgetc(STDIN);
            switch($continue) {
                case 'y':
                    break 2;
                case 'n':
                    break 3;
                default:
                    break;
            }
        }
    }
   
    exit(0);
}

main();

/* EOF */



Enter string of characters to search in:
ssssssssssssssssuuuuuuuuuuuuuuuussssssssssssssssmmmmmmmmmmmmmmmmmmmaaaaaaaaaaaaaaaannnnnnnnnnnnnnn

Enter string of characters to search for:
sussman

Congratulations, "sussman" was found 10 times!
Search query took 0.00026 seconds.

Try again? y/n
n

Name: Anonymous 2010-01-16 5:10

$continue = 'y';

DISREGARD

Name: Anonymous 2010-01-16 5:37

eval"\$$_++"for+split//,lc<>;print"SUSSMAN\n"x(sort{$a<=>$b}($s/3,$u,$m,$a,$n))[0]

Obviously, using Perl made it too easy. I might do one in C or something later.

Name: Anonymous 2010-01-16 5:40

>>27
Actually, that block passed to sort is quite useless. So this works too, and is a bit shorter too.

eval"\$$_++"for+split//,lc<>;print"SUSSMAN\n"x(sort($s/3,$u,$m,$a,$n))[0]

Name: Anonymous 2010-01-16 7:11

>>28
VALID LINE NOISE

Name: Anonymous 2010-01-16 9:44


#!/usr/bin/env ruby
h={}
STDIN.read().split(//).reject{|e|!("SUMAN".include?e)}.each{|e|h[e]?h[e]+=1.0:h[e]=1.0}
h["S"]&&h["S"]/=3
loop { h.each_pair{|k,v|v<1.0&&exit;h[k]-=1.0}; puts "SUSSMAN" }

Name: Anonymous 2010-01-16 10:51

(define count-suss
  (λ(string)
    (let ((string (string-downcase string))
          (count-s (λ(char string)
                     (let ((empty-s? (λ(s) (string=? s ""))))
                       (let loop ((string string)
                                  (count 0))
                         (if (empty-s? string)
                             count
                             (loop (substring string 1)
                                   (+ count (if (char=? char
                                                        (string-ref string 0))
                                                1
                                                0)))))))))
      (let ((s-count (count-s #\s string))
            (u-count (count-s #\u string))
            (m-count (count-s #\m string))
            (a-count (count-s #\a string))
            (n-count (count-s #\n string)))
        (min (quotient s-count 3)
             u-count
             m-count
             a-count
             n-count)))))

(define homework
  (λ(string)
    (let ((output (λ() (display 'sussman)(newline)))) ;'
      (let loop ((susscount (count-suss string)))
        (if (one? susscount)
            (output)
            (begin (output)
                   (loop (- susscount 1))))))))

Name: Anonymous 2010-01-16 10:55

>>31
Why don't you just convert the string to a list of chars with string->list instead of taking substrings of length 1 and using string-ref on that?

Name: Anonymous 2010-01-16 10:58

Oh man infinite loop...
(define homework
  (λ(string)
    (let ((output (λ() (display 'sussman)(newline))))
      (let loop ((susscount (count-suss string)))
        (cond ((< 0 susscount) (begin (output)
                                       (loop (- susscount 1)))))))))

Name: Anonymous 2010-01-16 11:01

>>32
No reason, really.

Name: Anonymous 2010-01-16 12:40

import Control.Monad.Instances
import Data.Function
import List

findSuss s =
   mapM_ (const $ putStrLn "sussman") $ takeWhile (== length "sussman")
                                      $ zipWith (subtract `on` length) =<< tail
                                      $ iterate (\\ "sussman") s

Name: Anonymous 2010-01-16 13:45

ENTERPRISE C!!!

#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
  char s[9],*p = argv[1];
  memset(s,0,9);
  if(p) for(;*p;p++) {
    s[*p=='S'?(s[0]?(s[2]?3:2):0):(*p=='U'?1:(*p=='M'?4:(*p=='A'?5:(*p=='N'?6:8))))]=*p;
    if(strlen(s)==7) { printf("%s\n",s); memset(s,0,9); }
  }
  return 0;
}

Name: Anonymous 2010-01-16 13:47

>>22

Funny, I was using getchar at first, not sure why I switched to scanf.

Anyways, here's a less disgraceful C version.

#include <stdio.h>

int main()
{
    char suss[300];
    char letters[] = "SUMANsuman";
    char count[5] = {0}; /* S, U, M, A, N */
   
    int x, c;
   
    printf("Enter a string: ");
    for (x = 0; (suss[x] = getchar()) != '\n'; x++);
   
    for (x = 0; suss[x] != '\n'; x++)
    {
        for (c = 0; c <= 9; c++)
        {
            if (suss[x] == letters[c])
            {
                if (c < 5)
                    count[c]++;
                else
                    count[c-5]++;
            }
        }
    }
   
    while (count[0] > 0)
    {
        if (count[0] >= 3 && count[1] > 0 && count[2] > 0 && count[3] > 0 && count[4] > 0)
            printf("SUSSMAN\n");
       
        count[0] -= 3;
        for (x = 1; x < 5; x++)
            count[x]--;
    }
   
    return 0;
}

Name: Anonymous 2010-01-16 14:01

>>9,10
What the fuck is that Array abomination?

My haskal version:
import Control.Arrow ((&&&))
import Data.List (group, sort, lookup)
import Data.Maybe (fromMaybe)
import Data.Char (toLower)

count = map (head &&& length) . group . sort . map toLower

find = (fromMaybe 0 .) . flip lookup

a /// b = minimum $ map (uncurry $ (quot . find a)) b

rearrange src pat = unwords . take n $ repeat pat
  where n = count src /// count pat

main = putStrLn . flip rearrange "SUSSMAN" =<< getLine


Gotta write a C one next; does C do TCO?

Name: Anonymous 2010-01-16 14:25

My C version:
#include <stdio.h>

int main(int argc, char **argv)
{
    int s, u, m, a, n, pos;
    char c;
    char cs[] = "SUSSMAN ";
    int* vs[] = {&s, &u, &s, &s, &m, &a, &n, &pos, 0};
    while ((c = getchar()) != '\n')
    {
        switch (c)
        {
            case 's': case 'S': ++s; break;
            case 'u': case 'U': ++u; break;
            case 'm': case 'M': ++m; break;
            case 'a': case 'A': ++a; break;
            case 'n': case 'N': ++n; break;
        }
        while (*vs[pos])
        {
            *vs[pos]--;
            printf("%c", cs[pos++]);
            pos &= 7;
        }
    }
    printf("\n");
    return 0;
}

Name: Anonymous 2010-01-16 14:44

>>39
oh fuck I'm stupid.
Add int _ = 1; somewhere and s/&pos/&_/.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List