𝗖𝗼𝗺𝗽𝘂𝘁𝗲𝗿𝘀 𝗔𝗿𝗲𝗻'𝘁 𝗦𝗺𝗮𝗿𝘁 Most people think computers are 𝘪𝘯𝘵𝘦𝘭𝘭𝘪𝘨𝘦𝘯𝘵. As a developer, I know better. I was building a file sorter and writing tests when I noticed something odd: the tests kept failing on "tar.gz" files but worked perfectly for everything else. The problem? I was using file.suffix to get the extension. It worked great for single extensions like .pdf or .jpg, but completely failed for compound extensions like .tar.gz. Why? Because: 𝗳𝗶𝗹𝗲.𝘀𝘂𝗳𝗳𝗶𝘅 𝗿𝗲𝘁𝘂𝗿𝗻𝘀 .𝗴𝘇 (𝗼𝗻𝗹𝘆 𝘁𝗵𝗲 𝗹𝗮𝘀𝘁 𝗽𝗮𝗿𝘁) 𝗳𝗶𝗹𝗲.𝘀𝘂𝗳𝗳𝗶𝘅𝗲𝘀 𝗿𝗲𝘁𝘂𝗿𝗻𝘀 ['.𝘁𝗮𝗿', '.𝗴𝘇'] (𝗮𝗹𝗹 𝗽𝗮𝗿𝘁𝘀) The fix was simple: "".𝗷𝗼𝗶𝗻(𝗳𝗶𝗹𝗲.𝘀𝘂𝗳𝗳𝗶𝘅𝗲𝘀) 𝗕𝘂𝘁 𝗵𝗲𝗿𝗲'𝘀 𝘁𝗵𝗲 𝗿𝗲𝗮𝗹 𝗹𝗲𝘀𝘀𝗼𝗻: the computer did exactly what it was told to do. It wasn't wrong. I just failed to communicate my intent properly. Without those tests, this bug would have been invisible:files silently miscategorized, no errors thrown, just wrong behavior lurking in production. 𝗧𝗵𝗶𝘀 𝗶𝘀 𝘄𝗵𝘆 𝘁𝗲𝘀𝘁𝗶𝗻𝗴 𝗺𝗮𝘁𝘁𝗲𝗿𝘀: Not because computers make mistakes, but because we do. Computers are fast, precise, and literal. But smart? Never. They'll happily execute our misunderstandings at lightning speed. Our job is to close the gap between what we think we're asking for and what we're actually asking for. #SoftwareDevelopment #Testing #Python #CodingLessons #DeveloperLife #automation
Why Computers Don't Make Mistakes, But We Do
More Relevant Posts
-
💡 Day 38 of 100 — Ones and Zeroes (#LeetCode 474) Today’s problem brought back the classic 0/1 Knapsack vibes but with a binary twist. It’s about choosing the largest subset of binary strings under limits for zeros (m) and ones (n). At first glance, it looks like a simple counting problem, but it quickly becomes a dynamic programming puzzle about balancing two constraints at once. 🧠 What I figured out Each string can be treated as an “item” with two costs number of 0s and number of 1s. The goal is to maximize the number of items chosen within the given limits. The trick is iterating backward in the DP array to avoid overwriting earlier results, a common knapsack technique. 💻 My thought process I initialized a 2D DP table where dp[i][j] represents the maximum subset size achievable with at most i zeros and j ones. Then, for every string, I counted its zeros and ones, and updated the DP table from the back to preserve correct state transitions. 📊 Complexity: Time — O(len(strs) × m × n) Space — O(m × n) 💬 Reflection This problem reminded me that even simple patterns like zeros and ones can hide deep optimization challenges. DP problems always test patience but when the logic clicks, it’s pure satisfaction. #100DaysOfLeetCode #Day38 #LeetCodeJourney #DSA #Coding
To view or add a comment, sign in
-
-
Day 56 – Raising Your Own Exceptions Sometimes it’s you who needs to throw the red flag 🚩 Use raise to enforce your own rules. def withdraw(amount): if amount <= 0: raise ValueError("Withdrawal amount must be positive!") print(f"Withdrawing ${amount}") withdraw(-50) 🧠 Output: ValueError: Withdrawal amount must be positive! 💡 Proactive exceptions prevent bigger bugs later. This is how real-world apps maintain data integrity and user safety. 👉 Where would you use a custom exception in your code? #Python #Debugging #CleanCode #DeveloperLife
To view or add a comment, sign in
-
🟥 1. C++ – Bad Example Demonstrates unsafe code that doesn’t verify if the player is alive before performing actions. Relies on basic structs without proper type safety. Can lead to runtime errors or undefined behavior. Highlights a common issue in older or less-structured C++ codebases. 🟩 2. Rust – Good Example Uses enums and pattern matching to represent safe, valid states. The compiler enforces handling of all possible cases (e.g., Alive, Dead). Prevents logical errors like calling methods on invalid objects. Rust’s strong type system eliminates many runtime bugs early. 🟩 3. C++ – Good Example (Using std::variant) Modern C++ can achieve Rust-like safety using std::variant and std::visit. Each player state (AlivePlayer, DeadPlayer) is modeled distinctly. The compiler ensures that all possible variants are handled safely. Demonstrates type-safe polymorphism without traditional inheritance. 💡 Summary Insight: Rust enforces safety at compile time by design, while modern C++ provides similar capabilities through advanced features like std::variant. This comparison shows how explicit state modeling leads to safer and more maintainable code.
To view or add a comment, sign in
-
-
🤔 Ever Wonder Why malloc() and Memory APIs Return void*? In C, malloc() returns a void* and that’s not just a random design choice. It’s one of the most elegant examples of type abstraction in system programming. Here’s the logic behind it 👇 🧠 1️⃣ The purpose of void* void* is a generic pointer type that can point to any data type. This means malloc() doesn’t need to know what you’ll store integers, structs, or arrays it simply hands you a chunk of raw memory. int *arr = (int *)malloc(10 * sizeof(int)); The cast tells the compiler what type of data you plan to use that memory for. ⚙️ 2️⃣ Consistency across memory APIs Other allocators like calloc(), realloc(), and even system-level functions (mmap(), kmalloc(), etc.) return void* too. This keeps memory allocation universal and reusable across various contexts. 🚫 3️⃣ Why C++ handles it differently C allows implicit conversion from void* to any pointer type. C++ doesn’t it enforces an explicit cast for stronger type safety, preventing subtle pointer-type mismatches. ⚡ Takeaway: Returning void* makes memory APIs generic, flexible, and language-agnostic a simple idea that keeps C powerful after all these years. #CProgramming #EmbeddedSystems #MemoryManagement #FirmwareDevelopment #SystemProgramming #LinuxKernel
To view or add a comment, sign in
-
-
🚀 Day 416 of #500DaysOfCode Problem: 1513. Number of Substrings With Only 1s Platform: LeetCode – Medium Today’s challenge was a classic binary-string problem that focuses on counting substrings composed only of '1' characters. Sounds simple—but with constraints up to 100,000 characters, brute force is impossible. 🔍 What I Learned The key insight is: Whenever you find a continuous streak of 1s of length k, it contributes: k⋅(k+1)2\frac{k \cdot (k+1)}{2}2k⋅(k+1)substrings made only of 1s. Example: 111 → • "1" (3 times) • "11" (2 times) • "111" (1 time) Total = 6 So instead of checking all substrings, we just: ➡️ Count lengths of 1-streaks ➡️ Use the formula ➡️ Keep sum modulo 1e9+7 🧠 Why This Problem Is Useful Builds intuition for pattern-counting in strings Reinforces how mathematical optimization replaces brute-force loops Helps in understanding frequency-based substring logic 📌 Output Examples Input: "0110111" → Output: 9 Input: "101" → Output: 2 Input: "111111" → Output: 21 💡 Reflection Simple logic + clever math = powerful optimization. This problem reminded me how often the pattern matters more than the individual characters. #500DaysOfCode #Day416 #LeetCode #Java #CodingJourney
To view or add a comment, sign in
-
-
Nothing hurts user experience more than "We're sorry, the service is temporarily unavailable." Especially when it's a third-party API you don't control. Instead of hoping for the best, I wrap all external API calls with this resilient Python decorator. It automatically handles retries with exponential backoff, ensuring your app remains resilient to temporary outages. 💪 Resilience: Survives network blips, API throttling, and temporary outages ⚡ Smart Backoff: Won't overwhelm the API with immediate retries 🔧 Reusable: One decorator protects all your API calls 📝 Logging: See exactly what's failing and when. Pro Tip: Combine this with circuit breakers for enterprise-grade resilience! What's the flakiest API you've ever had to integrate with? War stories welcome in the comments! 🍿 #Python #API #Microservices #Reliability #SoftwareArchitecture #BackendDevelopment #WebDevelopment #Resilience
To view or add a comment, sign in
-
-
Ever wondered how a tiny ++ can turn a perfectly good program into a mystery? I’ve been digging into some of the most notorious ways the increment operator can cause undefined behavior (UB). Below are seven classic (and definitely not‑to‑be‑copied) examples that illustrate why you should always respect sequence points and operator precedence. 1. i+++++i – Multiple increments without an intervening sequence point. The compiler can evaluate the left‑hand and right‑hand sides in any order, leading to unpredictable results. 2. i = i++ – The assignment and the post‑increment are unsequenced; the final value of i is undefined. 3. i = ++i + i – Mixing pre‑increment with other reads of the same variable creates a race condition in the abstract machine. 4. i = i = i + 1 – Chained assignments with side effects are a recipe for UB. 5. *i = i**++* – The ** is not a valid operator; even if it were, the combination of dereference and increment without a sequence point would be illegal. 6. std::cout << i+++++i; – The stream insertion operator evaluates its operands in an unspecified order, so the increments may happen before or after the output. 7. i = ++i + ++i; – Two pre‑increments on the same variable in a single expression are unsequenced, giving different results on different compilers. > These snippets are pure examples of bad practice. Do NOT use them in production code. Why does UB matter?Undefined behavior isn’t just a theoretical concern—it can cause crashes, silent data corruption, or security vulnerabilities that are incredibly hard to track down. Modern compilers often exploit UB for optimization, so what looks “harmless” today may break spectacularly tomorrow. I’d love to hear from youHave you ever stumbled upon a tricky UB case in C/C++? How did you debug it, and what lesson did you take away? Share your stories in the comments—let’s help each other write safer, more predictable code! #Cpp #UndefinedBehavior #CodeQuality #SoftwareEngineering #LearningFromMistakes
To view or add a comment, sign in
-
-
The real battle isn’t outside, it’s in your mind. Win there, and you win everywhere.” ⸻ Debugging and Logical Thinking (vs Syntax Errors) ⸻ Real-life meaning: In life, most battles are internal — not with the world, but with our thoughts, focus, and consistency. Once you control your thinking, you can handle any challenge outside. ⸻ C++ connection: In C++, the hardest part isn’t fixing syntax errors — the compiler already tells you those. The real battle is inside your logic — the way you think, design, and reason through a problem. If your logic (mind) is clear, your code (world) works fine. But if your logic is confused, no compiler can save you. ⸻ C++ program #include <iostream> using namespace std; int main() { int x = 10, y = 20; // Wrong logic — code compiles fine, but output is wrong if (x > y) { cout << "x is greater" << endl; } else { cout << "y is greater" << endl; } } The compiler sees no error, But your logic decides the result. The true debugging happens in your mind, not in your IDE. ⸻ If anyone wants to learn C++ through real-life scenarios like this, stay connected #cpp #cplusplus #codingmindset #programming #softwareengineering #debugging #learncpp #realworldcoding #developers #motivation #arattai #linkedinposts
To view or add a comment, sign in
-
-
I just hit a milestone I've been working toward for a while: I wrote my first function in a programming language I built from scratch 😊 I'm calling it sa (with .sa file type), and seeing it compile and execute felt like magic - even though I wrote every piece of that magic myself. Here's what the language looks like at this point: fn main() -> void { let message = "Hello, sa!"; print(message); } Clean and simple. But underneath, there's: → A lexer that tokenizes the source code → A parser that constructs an abstract syntax tree → A code generator built on LLVM that produces intermediate representation → Native compilation to ARM64 machine code The compiler generates this LLVM IR: define i32 @main() { entry: %message = alloca ptr, align 8 store ptr @0, ptr %message, align 8 %message1 = load ptr, ptr %message, align 8 call void @print(ptr %message1) ret i32 0 } And when I run it: $ ./myprogram Hello, sa! 😊Those two words on the terminal meant more to me than you might think. Why am I building this? Because I want to understand, at a fundamental level, how we communicate with machines. Not through frameworks, libraries, or abstractions built by others - but from first principles. I want to know what it feels like to tell a processor exactly what to do, in the most direct way possible, and watch it execute those instructions. There's something deeply empowering about bypassing decades of abstraction layers. About tracing the path from a human idea to electrical signals in silicon. About feeling truly in control of the machine, not just a user of someone else's tools. What's next? This is just the foundation. I'm planning to add: → A strong type system with inference → Pattern matching and algebraic data types → First-class functions and closures → ML-specific features for AI research My goal is to build a language that feels natural for machine learning research, while giving me complete control over how it compiles down to hardware. The journey matters more than the destination. Every compiler error I debugged, every segfault I traced, every moment I stared at LLVM IR trying to understand why the linker couldn't find _main - those taught me more than any tutorial ever could. I'm not sure anyone's interested at this point but if you are, please check out the GitHub repo at https://lnkd.in/eGZHdmE3 I am more than welcome anyone for contribution or collaboration to build this.
To view or add a comment, sign in
-
It's early morning and You are scrolling Linkedin posts? 𝗖𝗼𝗺𝗲 𝗶𝗻 and check my new series for 𝗖++ 𝗱𝗲𝘃𝗲𝗹𝗼𝗽𝗲𝗿𝘀 who are interested in the new, upcomming big wave in embeeded world - 𝗰𝗮𝗹𝗹𝗲𝗱 𝗥𝘂𝘀𝘁 🦀 𝗙𝗿𝗼𝗺 𝘀𝘁𝗱::𝘂𝗻𝗶𝗾𝘂𝗲_𝗽𝘁𝗿 𝘁𝗼 𝗕𝗼𝘅<𝗧> — 𝘁𝗵𝗲 𝗥𝘂𝘀𝘁 𝘄𝗮𝘆 𝗼𝗳 𝘀𝗮𝗳𝗲 𝗼𝘄𝗻𝗲𝗿𝘀𝗵𝗶𝗽 As a C++ embedded developer, you’ve probably used 𝘀𝘁𝗱::𝘂𝗻𝗶𝗾𝘂𝗲_𝗽𝘁𝗿 countless times to manage dynamic memory safely. But here’s the thing: - In 𝗥𝘂𝘀𝘁, safety isn’t something you add — it’s 𝗯𝘂𝗶𝗹𝘁 𝗶𝗻. In my latest blog post, I explain how 𝗥𝘂𝘀𝘁’𝘀 𝗕𝗼𝘅<𝗧> compares to 𝘀𝘁𝗱::𝘂𝗻𝗶𝗾𝘂𝗲_𝗽𝘁𝗿<𝗧>. You’ll learn: • How 𝗕𝗼𝘅<𝗧> achieves 𝘂𝗻𝗶𝗾𝘂𝗲 𝗼𝘄𝗻𝗲𝗿𝘀𝗵𝗶𝗽 without null pointers • Why 𝗺𝗲𝗺𝗼𝗿𝘆 𝗹𝗲𝗮𝗸𝘀 and 𝗻𝘂𝗹𝗹𝗽𝘁𝗿 𝗰𝗵𝗲𝗰𝗸𝘀 simply 𝗮𝗿𝗲 𝗻𝗼 𝗹𝗼𝗻𝗴 𝘁𝗵𝗲 𝗶𝘀𝘀𝘂𝗲𝘀 • How Rust replaces “trust the developer” with “trust the compiler” 𝗧𝗟;𝗗𝗥: 𝘀𝘁𝗱::𝘂𝗻𝗶𝗾𝘂𝗲_𝗽𝘁𝗿<𝗧> -> 𝗕𝗼𝘅<𝗧> 𝗱𝗼𝗻𝗲 𝗿𝗶𝗴𝗵𝘁 If you’ve ever wondered how Rust can bring 𝘀𝗮𝗳𝗲𝗿, 𝗰𝗹𝗲𝗮𝗻𝗲𝗿, 𝗮𝗻𝗱 𝗳𝗮𝘀𝘁𝗲𝗿 𝗰𝗼𝗱𝗲 to your embedded projects — this one’s for you. 𝗥𝗲𝗮𝗱 𝘁𝗵𝗲 𝗳𝘂𝗹𝗹 𝗽𝗼𝘀𝘁 𝘄𝗶𝘁𝗵 𝗲𝘅𝗮𝗺𝗽𝗹𝗲𝘀 𝗵𝗲𝗿𝗲: - https://lnkd.in/da-aysBZ What’s your biggest challenge when thinking about switching from C++ to Rust? Do You also believe 𝗥𝘂𝘀𝘁 will have major sharehold in embeeded programming, especially in safety critical projects, in next five years? #Rust #Cplusplus #EmbeddedSystems #MemorySafety #RustLang #SoftwareEngineering #Programming
To view or add a comment, sign in
Explore related topics
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development