Memoization in Dynamic Programming Through Examples

Dynamic programming is a technique for solving problems, whose solution can be expressed recursively in terms of solutions of overlapping sub-problems. A gentle introduction to this can be found in How Does DP Work? Dynamic Programming Tutorial.

This lesson was originally published at https://algodaily.com, where I maintain a technical interview course and write think-pieces for ambitious developers.

Memoization is an optimization process. In simple terms, we store the intermediate results of the solutions of sub-problems, allowing us to speed up the computation of the overall solution. The improvement can be reduced to an exponential time solution to a polynomial time solution, with an overhead of using additional memory for storing intermediate results.

Let’s understand how dynamic programming works with memoization with a simple example.

Image for post

Fibonacci Numbers

You have probably heard of [**Fibonacci numbers**](https://algodaily.com/challenges/fibonacci-sequence/) several times in the past, especially regarding recurrence relations or writing recursive functions. Today we’ll see how this simple example gives us a true appreciation of the power of dynamic programming and memoization.

Definition of Fibonacci Numbers

The nth Fibonacci number f(n) is defined as:

f(0) = 0                                       // base case
f(1) = 1                                       // base case 
f(n) = f(n-1) + f(n-2)    for n>1              // recursive case

The sequence of Fibonacci numbers generated from the above expressions is:

0 1 1 2 3 5 8 13 21 34 ...

Pseudo-code for Fibonacci Numbers

When implementing the mathematical expression given above, we can use the following recursive pseudo-code attached.

Routine: f(n)
Output: Fibonacci number at the nth place

Base case:
1\. if n==0 return 0
2\. if n==1 return 1
Recursive case:
1\. temp1 = f(n-1)
2\. temp2 = f(n-2)
3\. return temp1+temp2

The recursion tree shown below illustrates how the routine works for computing f(5) or fibonacci(5).

If we look closely at the recursive tree, we can see that the function is computed twice for f(3), thrice for f(2) and many times for the base cases f(1) and f(0). The overall complexity of this pseudo-code is therefore exponential O(2n). We can very well see how we can achieve massive speedups by storing the intermediate results and using them when needed.

Image for post

Memoization of Fibonacci Numbers: From Exponential Time Complexity to Linear Time Complexity

To speed things up, let’s look at the structure of the problem. f(n) is computed from f(n-1) and f(n-2). As such, we only need to store the intermediate result of the function computed for the previous two numbers. The pseudo-code to achieve this is provided here.

The figure below shows how the pseudo-code is working for f(5). Notice how a very simple memoization technique that uses two extra memory slots has reduced our time complexity from exponential to linear (**O(n)**).

Image for post

Routine: fibonacciFast
Input: n
Output: Fibonacci number at the nth place
Intermediate storage: n1, n2 to store f(n-1) and f(n-2) respectively
1\. if (n==0) return 0
2\. if (n==1) return 1
3\. n1 = 1
4\. n2 = 0
5\. for 2 .. n
    a. result = n1+n2           // gives f(n)
    b.   n2 = n1                // set up f(n-2) for next number
    c.   n1 = result            // set up f(n-1) for next number
6\. return result

Maximizing Rewards While Path Finding Through a Grid

Now that we understand memoization a little better, let’s move on to our next problem. Suppose we have an m * n grid, where each cell has a “reward” associated with it. Let’s also assume that there’s a robot placed at the starting location, and that it has to find its way to a “goal cell”. While it’s doing this, it will be judged by the path it chooses. We want to get to the “goal” via a path that collects the maximum reward. The only moves allowed are “up” or “right”.

#data-structures #computer-science #software-development #dynamic-programming #algorithms #algorithms

What is GEEK

Buddha Community

Memoization in Dynamic Programming Through Examples

All You Need to Know About Dynamic Programming

In this article, I will introduce the concept of dynamic programming, developed by Richard Bellman in the 1950s, a powerful algorithm design technique to solve problems by breaking them down into smaller problems, storing their solutions, and combining these to get to the solution of the original problem.

The hardest problems asked in FAANG coding interviews usually fall under this category. It is likely that you will get tasked with solving one during your interviews, hence the importance of knowing this technique. I will explain what dynamic programming is, give you a recipe to tackle dynamic programming problems, and will take you through a few examples so that you can understand better when and how to apply it.

#dynamic-programming #programming-interviews #programming

Bhakti Rane

1624531051

Alerts4Dynamics - Alerts / Notifications Management in Dynamics 365 CRM

Alerts4Dynamics is productivity app for Dynamics 365 CRM that helps to create, schedule, manage and track alerts. It helps to notify and pass relevant information to target audience right within Dynamics 365 CRM. These notifications can be created and displayed indefinitely or for a defined scheduled period. Notification button is available on all entities and can be accessed from anywhere in the CRM.
Features
• Create Announcement and Rule Based/Record Based alerts.
• Alerts can be sent as Pop-ups, Form Notifications or Email to target Dynamics 365 CRM users.
• Categorize alerts as Information, Warning or Critical.
• Track log of read/dismissed alerts by users.
• Define process start date from when the notifications will start getting created and process end date when creation of new notifications will stop. Also, add the display end date for notification.

https://www.inogic.com/product/productivity-apps/add-manage-schedule-notifications-alerts-4-dynamics-365-crm

#dynamics 365 pop-up alert #dynamics 365 email alerts #dynamics 365 bulk alerts #dynamics crm pop-up alert #dynamics 365 notifications #dynamics crm alert

Bhakti Rane

1625057623

Click2Undo - 1 Click App to restore Dynamics 365 CRM data to its last known state

Undo changes & restore records in Dynamics 365 CRM with a single click

Click2Undo is a productivity app that helps you to undo changes in the data in Dynamics 365 CRM with a single click. Be it the last change that you’d want to restore, or the changes that were done in the past which you would like to get back, Click2Undo can do it without any hassle. This provides a safety net within which users can conduct day-to-day activities without fear of losing data due to human or technical errors.
Click2Undo is available for Dynamics CRM 8.2 and above, Dataverse (Power Apps). It supports deployment models - On-Premises and Online.
Features
• Entity Support: Click2Undo provides support to all OOB as well as Custom Entities
• Undo Last Changes: Ability to restore the last changes done to a Dynamics 365 CRM record by clicking the Click2Undo button
• Undo Past Changes: Ability to undo past changes made to multiple fields on Dynamics 365 CRM records in one go using History button
• Undo Bulk Changes: Ability to undo changes on multiple records at one go.

#restore last state of dynamics 365 records #restoring deleted dynamics 365 records #recovering deleted dynamics 365 records #recover deleted dynamics crm records #dynamics 365 online recover deleted records #restore records dynamics crm

Memoization in Dynamic Programming Through Examples

Dynamic programming is a technique for solving problems, whose solution can be expressed recursively in terms of solutions of overlapping sub-problems. A gentle introduction to this can be found in How Does DP Work? Dynamic Programming Tutorial.

This lesson was originally published at https://algodaily.com, where I maintain a technical interview course and write think-pieces for ambitious developers.

Memoization is an optimization process. In simple terms, we store the intermediate results of the solutions of sub-problems, allowing us to speed up the computation of the overall solution. The improvement can be reduced to an exponential time solution to a polynomial time solution, with an overhead of using additional memory for storing intermediate results.

Let’s understand how dynamic programming works with memoization with a simple example.

Image for post

Fibonacci Numbers

You have probably heard of [**Fibonacci numbers**](https://algodaily.com/challenges/fibonacci-sequence/) several times in the past, especially regarding recurrence relations or writing recursive functions. Today we’ll see how this simple example gives us a true appreciation of the power of dynamic programming and memoization.

Definition of Fibonacci Numbers

The nth Fibonacci number f(n) is defined as:

f(0) = 0                                       // base case
f(1) = 1                                       // base case 
f(n) = f(n-1) + f(n-2)    for n>1              // recursive case

The sequence of Fibonacci numbers generated from the above expressions is:

0 1 1 2 3 5 8 13 21 34 ...

Pseudo-code for Fibonacci Numbers

When implementing the mathematical expression given above, we can use the following recursive pseudo-code attached.

Routine: f(n)
Output: Fibonacci number at the nth place

Base case:
1\. if n==0 return 0
2\. if n==1 return 1
Recursive case:
1\. temp1 = f(n-1)
2\. temp2 = f(n-2)
3\. return temp1+temp2

The recursion tree shown below illustrates how the routine works for computing f(5) or fibonacci(5).

If we look closely at the recursive tree, we can see that the function is computed twice for f(3), thrice for f(2) and many times for the base cases f(1) and f(0). The overall complexity of this pseudo-code is therefore exponential O(2n). We can very well see how we can achieve massive speedups by storing the intermediate results and using them when needed.

Image for post

Memoization of Fibonacci Numbers: From Exponential Time Complexity to Linear Time Complexity

To speed things up, let’s look at the structure of the problem. f(n) is computed from f(n-1) and f(n-2). As such, we only need to store the intermediate result of the function computed for the previous two numbers. The pseudo-code to achieve this is provided here.

The figure below shows how the pseudo-code is working for f(5). Notice how a very simple memoization technique that uses two extra memory slots has reduced our time complexity from exponential to linear (**O(n)**).

Image for post

Routine: fibonacciFast
Input: n
Output: Fibonacci number at the nth place
Intermediate storage: n1, n2 to store f(n-1) and f(n-2) respectively
1\. if (n==0) return 0
2\. if (n==1) return 1
3\. n1 = 1
4\. n2 = 0
5\. for 2 .. n
    a. result = n1+n2           // gives f(n)
    b.   n2 = n1                // set up f(n-2) for next number
    c.   n1 = result            // set up f(n-1) for next number
6\. return result

Maximizing Rewards While Path Finding Through a Grid

Now that we understand memoization a little better, let’s move on to our next problem. Suppose we have an m * n grid, where each cell has a “reward” associated with it. Let’s also assume that there’s a robot placed at the starting location, and that it has to find its way to a “goal cell”. While it’s doing this, it will be judged by the path it chooses. We want to get to the “goal” via a path that collects the maximum reward. The only moves allowed are “up” or “right”.

#data-structures #computer-science #software-development #dynamic-programming #algorithms #algorithms

Riley Lambert

Riley Lambert

1656295532

How to Create a CSS Glitch Animation from Scratch

Learn How to Create Glitch Effect with CSS. Let's Create a CSS Glitch Animation from Scratch
 

Do you remember the earlier television sets right? Then you definitely will remember the glitches effects!

You have also noticed that nowadays glitchy effects are quite trendy. Let’s dive in and create the most catching glitch effect for our website!

Create HTML

  • Create <div> with the id "example".
  • Add three <h2> tags and input your content on which the glitch effect should be applied.
<div id="example">
  <h2>W3DOCS</h2>
  <h2>W3DOCS</h2>
  <h2>W3DOCS</h2>
</div>

Add CSS

  • Style the first <h2> tag by specifying its color, font-size, letter-spacing and font-weight. Set the text-align property to "center" and define the animation.
  • Use :nth-child() pseudo-class so as to put style to the next two <h2> tags. The :nth-child() pseudo-class selects and styles elements based on their index. For both the second and third child elements, specify the color and animation.
  • Define the starting and the ending point of animation. The keyframe declaration block includes CSS properties and their values. The keyframe selector can start with a percentage (%) or with the keywords “from” (same as 0%) and “to” (same as 100%). 0% is a starting point of the animation, 100% is the endpoint. The values define how the animation should behave at some point. Here, we use the CSS transform and the opacity properties, where the first property specifies a three-dimensional transformation of the element and the second one sets the level of transparency of an element.
h2 {
  text-align: center;
  color: #d9fff9;
  font-size: 80px;
  letter-spacing: 6px;
  font-weight: 300;
  margin: 0;
  line-height: 0;
  animation: glitch1 0.5s infinite;
}

h2:nth-child(2) {
  color: #0ef0e1;
  animation: glitch2 1.0s infinite;
}

h2:nth-child(3) {
  color: #ff94eb;
  animation: glitch3 1.0s infinite;
}

@keyframes glitch1 {
  0% {
    transform: none;
    opacity: 1;
  }
  50% {
    transform: skew(-2deg, 0.6deg);
    opacity: 0.75;
  }
  100% {
    transform: none;
    opacity: 1;
  }
}

@keyframes glitch2 {
  0% {
    transform: none;
    opacity: 0.25;
  }
  50% {
    transform: translate(-3px, -1px);
    opacity: 0.5;
  }
  100% {
    transform: none;
    opacity: 0.25;
  }
  @keyframes glitch3 {
    0% {
      transform: none;
      opacity: 0.25;
    }
    50% {
      transform: translate(3px, 1px);
      opacity: 0.5;
    }
    100% {
      transform: none;
      opacity: 0.25;
    }
  }

Now let’s bring all the parts together and see the result!

Example of creating a glitchy effect:

<!DOCTYPE html>
<html>
  <head>
    <title>The title of the document</title>
    <style>
      body {
        background-color: #eee;
      }
      #example {
        width: 450px;
        margin: 250px auto;
      }
      h2 {
        text-align: center;
        color: #d9fff9;
        font-size: 80px;
        letter-spacing: 6px;
        font-weight: 300;
        margin: 0;
        line-height: 0;
        animation: glitch1 0.5s infinite;
      }
      h2:nth-child(2) {
        color: #0ef0e1;
        animation: glitch2 1.0s infinite;
      }
      h2:nth-child(3) {
        color: #ff94eb;
        animation: glitch3 1.0s infinite;
      }
      @keyframes glitch1 {
        0% {
          transform: none;
          opacity: 1;
        }
        50% {
          transform: skew(-2deg, 0.6deg);
          opacity: 0.75;
        }
        100% {
          transform: none;
          opacity: 1;
        }
      }
      @keyframes glitch2 {
        0% {
          transform: none;
          opacity: 0.25;
        }
        50% {
          transform: translate(-3px, -1px);
          opacity: 0.5;
        }
        100% {
          transform: none;
          opacity: 0.25;
        }
      }
      @keyframes glitch3 {
        0% {
          transform: none;
          opacity: 0.25;
        }
        50% {
          transform: translate(3px, 1px);
          opacity: 0.5;
        }
        100% {
          transform: none;
          opacity: 0.25;
        }
      }
    </style>
  </head>
  <body>
    <div id="example">
      <h2>W3DOCS</h2>
      <h2>W3DOCS</h2>
      <h2>W3DOCS</h2>
    </div>
  </body>
</html>

Example of creating a glitchy effect with more @keyframes values:

<!DOCTYPE html>
<html>
  <head>
    <title>The title of the document</title>
    <style>
      body {
        background-color: #eee;
      }
      #example {
        width: 450px;
        margin: 250px auto;
      }
      h2 {
        text-align: center;
        color: #d9fff9;
        font-size: 80px;
        letter-spacing: 6px;
        font-weight: 300;
        margin: 0;
        line-height: 0;
        animation: glitch1 3.5s infinite;
      }
      h2:nth-child(2) {
        color: #0ef0e1;
        animation: glitch2 2.5s infinite;
      }
      h2:nth-child(3) {
        color: #ff94eb;
        animation: glitch3 2.5s infinite;
      }
      @keyframes glitch1 {
        0% {
          transform: none;
          opacity: 1;
        }
        8% {
          transform: skew(-0.5deg, -0.9deg);
          opacity: 0.75;
        }
        10% {
          transform: none;
          opacity: 1;
        }
        28% {
          transform: none;
          opacity: 1;
        }
        30% {
          transform: skew(0.8deg, -0.1deg);
          opacity: 0.75;
        }
        33% {
          transform: none;
          opacity: 1;
        }
        45% {
          transform: none;
          opacity: 1;
        }
        55% {
          transform: skew(-1deg, 0.2deg);
          opacity: 0.75;
        }
        60% {
          transform: none;
          opacity: 1;
        }
        72% {
          transform: none;
          opacity: 1;
        }
        78% {
          transform: skew(0.4deg, 1deg);
          opacity: 0.75;
        }
        80% {
          transform: none;
          opacity: 1;
        }
        100% {
          transform: none;
          opacity: 1;
        }
      }
      @keyframes glitch2 {
        0% {
          transform: none;
          opacity: 0.25;
        }
        8% {
          transform: translate(-2px, -3px);
          opacity: 0.5;
        }
        10% {
          transform: none;
          opacity: 0.25;
        }
        28% {
          transform: none;
          opacity: 0.25;
        }
        30% {
          transform: translate(-5px, -2px);
          opacity: 0.5;
        }
        33% {
          transform: none;
          opacity: 0.25;
        }
        45% {
          transform: none;
          opacity: 0.25;
        }
        55% {
          transform: translate(-5px, -1px);
          opacity: 0.5;
        }
        60% {
          transform: none;
          opacity: 0.25;
        }
        72% {
          transform: none;
          opacity: 0.25;
        }
        78% {
          transform: translate(-2px, -6px);
          opacity: 0.5;
        }
        80% {
          transform: none;
          opacity: 0.25;
        }
        100% {
          transform: none;
          opacity: 0.25;
        }
      }
      @keyframes glitch3 {
        0% {
          transform: none;
          opacity: 0.25;
        }
        8% {
          transform: translate(2px, 3px);
          opacity: 0.5;
        }
        10% {
          transform: none;
          opacity: 0.25;
        }
        28% {
          transform: none;
          opacity: 0.25;
        }
        30% {
          transform: translate(5px, 2px);
          opacity: 0.5;
        }
        33% {
          transform: none;
          opacity: 0.25;
        }
        45% {
          transform: none;
          opacity: 0.25;
        }
        55% {
          transform: translate(5px, 1px);
          opacity: 0.5;
        }
        60% {
          transform: none;
          opacity: 0.25;
        }
        72% {
          transform: none;
          opacity: 0.25;
        }
        78% {
          transform: translate(2px, 6px);
          opacity: 0.5;
        }
        80% {
          transform: none;
          opacity: 0.25;
        }
        100% {
          transform: none;
          opacity: 0.25;
        }
      }
    </style>
  </head>
  <body>
    <div id="example">
      <h2>W3DOCS</h2>
      <h2>W3DOCS</h2>
      <h2>W3DOCS</h2>
    </div>
  </body>
</html>

Example of creating a glitchy effect with the :hover selector:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      .content {
        display: flex;
        width: 100vw;
        height: 100vh;
        background-color: black;
        background-image: url("https://images.unsplash.com/photo-1489875347897-49f64b51c1f8?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjM4MDE5fQ&auto=format&fit=crop&w=1050&q=80");
        background-repeat: no-repeat;
        background-position: center;
        background-size: cover;
      }
      .text {
        margin: auto;
        font-family: 'Montserrat', sans-serif;
        font-size: 120px;
        text-transform: uppercase;
      }
      .glitch {
        position: relative;
        color: white;
        mix-blend-mode: lighten;
      }
      .glitch:before,
      .glitch:after {
        content: attr(data-text);
        position: absolute;
        top: 0;
        width: 100%;
        background: black;
        clip: rect(0, 0, 0, 0);
      }
      .glitch:before {
        left: -1px;
        text-shadow: 1px 0 rgba(255, 0, 0, 0.7);
      }
      .glitch:after {
        left: 1px;
        text-shadow: -1px 0 rgba(0, 0, 255, 0.7);
      }
      .glitch:hover:before {
        text-shadow: 4px 0 rgba(255, 0, 0, 0.7);
        animation: glitch-loop-1 0.8s infinite ease-in-out alternate-reverse;
      }
      .glitch:hover:after {
        text-shadow: -5px 0 rgba(0, 0, 255, 0.7);
        animation: glitch-loop-2 0.8s infinite ease-in-out alternate-reverse;
      }
      @keyframes glitch-loop-1 {
        0% {
          clip: rect(36px, 9999px, 9px, 0);
        }
        25% {
          clip: rect(25px, 9999px, 99px, 0);
        }
        50% {
          clip: rect(50px, 9999px, 102px, 0);
        }
        75% {
          clip: rect(30px, 9999px, 92px, 0);
        }
        100% {
          clip: rect(91px, 9999px, 98px, 0);
        }
      }
      @keyframes glitch-loop-2 {
        0% {
          top: -1px;
          left: 1px;
          clip: rect(65px, 9999px, 119px, 0);
        }
        25% {
          top: -6px;
          left: 4px;
          clip: rect(79px, 9999px, 19px, 0);
        }
        50% {
          top: -3px;
          left: 2px;
          clip: rect(68px, 9999px, 11px, 0);
        }
        75% {
          top: 0px;
          left: -4px;
          clip: rect(95px, 9999px, 53px, 0);
        }
        100% {
          top: -1px;
          left: -1px;
          clip: rect(31px, 9999px, 149px, 0);
        }
      }
    </style>
  </head>
  <body>
    <div class="content">
      <h1 class="text glitch is-glitching" data-text="Hover me!">Hover me!</h1>
    </div>
  </body>
</html>

Let’s see another example:

Example of creating a glitchy effect using a linear-gradient:

<!DOCTYPE html>
<html>
  <head>
    <title>The title of the document</title>
    <style>
      body,
      h1 {
        padding: 0;
        margin: 0;
        font-family: 'Montserrat', sans-serif;
      }
      #example {
        height: 100vh;
        width: 100%;
        margin: 0;
        padding: 0;
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        background: linear-gradient(rgba(5, 5, 5, 0.6), rgba(0, 0, 0, 0)), repeating-linear-gradient(0, transparent, transparent 2px, black 3px, black 3px), url("https://images.unsplash.com/photo-1528372444006-1bfc81acab02?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=675&q=80");
        background-size: cover;
        background-position: center;
        z-index: 1;
      }
      #wrapper {
        text-align: center;
      }
      .glitch {
        position: relative;
        color: white;
        font-size: 4em;
        letter-spacing: .4em;
        animation: glitch-skew 0.5s infinite linear alternate-reverse;
      }
      .glitch::after {
        content: attr(data-text);
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        left: -2px;
        text-shadow: -2px 0 #00fff9, 2px 2px #ff00c1;
        animation: glitch-anim2 1s infinite linear alternate-reverse;
      }
      @keyframes glitch-anim {
        0% {
          clip: rect(30px, 9999px, 42px, 0);
          transform: skew(0.85deg);
        }
        5% {
          clip: rect(59px, 9999px, 21px, 0);
          transform: skew(0.34deg);
        }
        10% {
          clip: rect(99px, 9999px, 15px, 0);
          transform: skew(0.01deg);
        }
        15% {
          clip: rect(25px, 9999px, 61px, 0);
          transform: skew(0.97deg);
        }
        20% {
          clip: rect(35px, 9999px, 42px, 0);
          transform: skew(0.94deg);
        }
        25% {
          clip: rect(39px, 9999px, 62px, 0);
          transform: skew(0.31deg);
        }
        30% {
          clip: rect(62px, 9999px, 55px, 0);
          transform: skew(0.9deg);
        }
        35% {
          clip: rect(36px, 9999px, 31px, 0);
          transform: skew(0.13deg);
        }
        40% {
          clip: rect(27px, 9999px, 26px, 0);
          transform: skew(0.01deg);
        }
        45% {
          clip: rect(55px, 9999px, 9px, 0);
          transform: skew(0.5deg);
        }
        50% {
          clip: rect(69px, 9999px, 73px, 0);
          transform: skew(0.85deg);
        }
        55% {
          clip: rect(53px, 9999px, 89px, 0);
          transform: skew(0.15deg);
        }
        60% {
          clip: rect(20px, 9999px, 28px, 0);
          transform: skew(0.62deg);
        }
        65% {
          clip: rect(81px, 9999px, 28px, 0);
          transform: skew(0.1deg);
        }
        70% {
          clip: rect(54px, 9999px, 93px, 0);
          transform: skew(0.3deg);
        }
        75% {
          clip: rect(22px, 9999px, 6px, 0);
          transform: skew(0.84deg);
        }
        80% {
          clip: rect(23px, 9999px, 5px, 0);
          transform: skew(0.55deg);
        }
        85% {
          clip: rect(24px, 9999px, 76px, 0);
          transform: skew(0.68deg);
        }
        90% {
          clip: rect(3px, 9999px, 29px, 0);
          transform: skew(0.48deg);
        }
        95% {
          clip: rect(43px, 9999px, 95px, 0);
          transform: skew(0.37deg);
        }
        100% {
          clip: rect(58px, 9999px, 66px, 0);
          transform: skew(0.05deg);
        }
      }
      @keyframes glitch-anim2 {
        0% {
          clip: rect(66px, 9999px, 28px, 0);
          transform: skew(0.12deg);
        }
        5% {
          clip: rect(85px, 9999px, 40px, 0);
          transform: skew(0.7deg);
        }
        10% {
          clip: rect(14px, 9999px, 33px, 0);
          transform: skew(0.81deg);
        }
        15% {
          clip: rect(48px, 9999px, 76px, 0);
          transform: skew(0.57deg);
        }
        20% {
          clip: rect(77px, 9999px, 16px, 0);
          transform: skew(0.4deg);
        }
        25% {
          clip: rect(15px, 9999px, 43px, 0);
          transform: skew(0.27deg);
        }
        30% {
          clip: rect(33px, 9999px, 11px, 0);
          transform: skew(0.84deg);
        }
        35% {
          clip: rect(50px, 9999px, 51px, 0);
          transform: skew(0.16deg);
        }
        40% {
          clip: rect(52px, 9999px, 11px, 0);
          transform: skew(0.21deg);
        }
        45% {
          clip: rect(39px, 9999px, 58px, 0);
          transform: skew(0.98deg);
        }
        50% {
          clip: rect(88px, 9999px, 42px, 0);
          transform: skew(0.42deg);
        }
        55% {
          clip: rect(98px, 9999px, 11px, 0);
          transform: skew(0.51deg);
        }
        60% {
          clip: rect(73px, 9999px, 73px, 0);
          transform: skew(0.81deg);
        }
        65% {
          clip: rect(82px, 9999px, 59px, 0);
          transform: skew(1deg);
        }
        70% {
          clip: rect(64px, 9999px, 84px, 0);
          transform: skew(0.94deg);
        }
        75% {
          clip: rect(41px, 9999px, 44px, 0);
          transform: skew(0.38deg);
        }
        80% {
          clip: rect(23px, 9999px, 35px, 0);
          transform: skew(0.54deg);
        }
        85% {
          clip: rect(20px, 9999px, 100px, 0);
          transform: skew(0.76deg);
        }
        90% {
          clip: rect(9px, 9999px, 96px, 0);
          transform: skew(0.64deg);
        }
        95% {
          clip: rect(29px, 9999px, 82px, 0);
          transform: skew(0.47deg);
        }
        100% {
          clip: rect(15px, 9999px, 94px, 0);
          transform: skew(0.76deg);
        }
      }
      @keyframes glitch-skew {
        0% {
          transform: skew(2deg);
        }
        10% {
          transform: skew(4deg);
        }
        20% {
          transform: skew(4deg);
        }
        30% {
          transform: skew(-2deg);
        }
        40% {
          transform: skew(4deg);
        }
        50% {
          transform: skew(2deg);
        }
        60% {
          transform: skew(-3deg);
        }
        70% {
          transform: skew(-1deg);
        }
        80% {
          transform: skew(-3deg);
        }
        90% {
          transform: skew(-2deg);
        }
        100% {
          transform: skew(-2deg);
        }
      }
    </style>
  </head>
  <body>
    <div id="example">
      <div id="wrapper">
        <h1 class="glitch" data-text="glitch">glitch</h1>
      </div>
    </div>
  </body>
</html>

#css #html #programming #webdev